#!/usr/bin/perl -w
# $Id$
# This script (sophomorix-test) is maintained by Rüdiger Beck
# It is Free Software (License GPLv3)
# If you find errors, contact the author
# jeffbeck@web.de  or  jeffbeck@gmx.de

# Bibliotheken

# use utf8;
use strict;
use Getopt::Long;
use Sophomorix::SophomorixConfig;
use Sophomorix::SophomorixBase;
#use Sophomorix::SophomorixFiles;
use Sophomorix::SophomorixPgLdap;
use Sophomorix::SophomorixTest;
use Test::More "no_plan";
Getopt::Long::Configure ("bundling");

use DBI;
use Net::LDAP;
use Sys::Hostname;

my @arguments = @ARGV;

system("install -d /root/sophomorix-test");

$Conf::log_level=1;
my $help=0;
my $info=0;

# Parsen der Optionen
my $testopt=GetOptions(
           "verbose|v+" => \$Conf::log_level,
           "help|h" => \$help,
           "info|i" => \$info,
          );

# Prüfen, ob Optionen erkannt wurden
&check_options($testopt);

# --help
if ($help==1) {
   # Scriptname ermitteln
   my @list = split(/\//,$0);
   my $scriptname = pop @list;
   # Befehlbeschreibung
   print "\n$scriptname tests sophomorix-workstation.\n",
         " It should only be used on test systems!\n";
   print('
Options
  -h  / --help

Please see the sophomorix-test-workstation(8) man pages for full documentation
');
   print "\n";
   exit;
}

# --info
if ($info==1) {
    print "Option --info not defined.\n";
    exit;
}

############################################################
# Start
############################################################
&log_script_start(@arguments);
&check_connections();

# repair.directories einlesen ???
&get_alle_verzeichnis_rechte();

# fetch permission for all homes
&fetch_repairhome();

my $server=&hostname();
chomp($server);

my $win_magic="2147483647";

# sid
my $sid_string=`net getlocalsid`;
chomp($sid_string);
my ($rubbish,$sid) = split(/: /,$sid_string);

my $usid;
my $gsid;

# save all home here, overwrite homes 
# key:   login 
# value: home
my %last_home=();

my $today=`date +%d.%m.%Y`;
my $today_pg=`date +%Y-%m-%d`;
chomp($today);
chomp($today_pg);

print "\nToday is $today (pg: $today_pg)\n";
my $verbose=0;

my %account=();
my %account_ldap=();


my $ws_file="/etc/linuxmuster/workstations";

print '
###########################################################################
#                                                                         #
#              CHECKING THAT HOSTS DO NOT EXIST ALREADY                   #
#                                                                         #
###########################################################################
';
# exam account
&check_account_nonexists_id("a100pc01");
&check_account_nonexists_id("a100pc02");
&check_account_nonexists_id("b10pc01");
&check_account_nonexists_id("b10pc02");
&check_account_nonexists_id("printer01");
&check_account_nonexists_id("Printer01");
# homes
&check_nonexistence("/home/workstations/a100/a100pc01");
&check_nonexistence("/home/workstations/a100/a100pc02");
&check_nonexistence("/home/workstations/B10/b10pc01");
&check_nonexistence("/home/workstations/B10/b10pc01");
&check_nonexistence("/home/workstations/b10/b10pc02");
&check_nonexistence("/home/workstations/b10/b10pc02");
&check_nonexistence("/home/workstations/B10/B10PC01");
&check_nonexistence("/home/workstations/B10/B10PC01");
&check_nonexistence("/home/workstations/b10/B10PC02");
&check_nonexistence("/home/workstations/b10/B10PC02");
&check_nonexistence("/home/workstations/printer/printer01");
&check_nonexistence("/home/workstations/printer/Printer01");
&check_nonexistence("/home/workstations/Printer/printer01");
&check_nonexistence("/home/workstations/Printer/Printer01");
# computer account
&check_account_nonexists_id("a100pc01\$");
&check_account_nonexists_id("a100pc02\$");
&check_account_nonexists_id("b10pc01\$");
&check_account_nonexists_id("b10pc02\$");
&check_account_nonexists_id("printer01\$");
&check_account_nonexists_id("Printer01\$");


print '
###########################################################################
#                                                                         #
#                              ADDING LINES                               #
#                                                                         #
###########################################################################
';
my @ws_to_add=(
     "",
     "a100;a100pc01;abc;00:11:22:33:44:01;10.10.1.1;255.240.0.0;1;1;1;1;22;;",
     "a100;a100pc02;abc;00:11:22:33:44:02;10.10.1.2;255.240.0.0;1;1;1;1;22;;",
     "B10;B10PC01;HWK-2;00:11:22:33:44:03;10.10.2.1;255.240.0.0;1;1;1;1;0;;",
     "B10;B10PC02;HWK-2;00:11:22:33:44:04;10.10.2.2;255.240.0.0;1;1;1;1;0;;",
     "Printer;Printer01;prn;00:11:22:33:44:05;10.10.3.1;255.240.0.0;1;1;1;0;0;;",
   );
foreach my $ws (@ws_to_add){
   &append_line($ws,$ws_file);
}


# run sophomorix-workstation
&run_command("sophomorix-workstation --sync-accounts",$verbose);



print '
###########################################################################
#                                                                         #
#                    HOST 1-4 SHOULD EXIST, HOST 5 NOT                    #
#                                                                         #
###########################################################################
';
# account 1:
%account = &fetch_single_account("uid='a100pc01'");
%account_ldap=&fetch_ldap_account($account{'uid'});
&ok_account("gid", "a100");
&ok_account("adminclass", "a100");
&ok_account("firstname", "Exam");
&ok_account("surname", "Account");
&ok_account("gecos", "ExamAccount");
&ok_account("cn", "ExamAccount");
&ok_account("displayname", "ExamAccount");
&check_existence("/home/workstations/a100/a100pc01");
&ok_account("sambaacctflags","[UX]");
#
&check_account_exists_id("a100pc01");
&check_account_exists_id("a100pc01\$");

# account 2:
%account = &fetch_single_account("uid='a100pc02'");
%account_ldap=&fetch_ldap_account($account{'uid'});
&ok_account("gid", "a100");
&ok_account("adminclass", "a100");
&ok_account("firstname", "Exam");
&ok_account("surname", "Account");
&ok_account("gecos", "ExamAccount");
&ok_account("cn", "ExamAccount");
&ok_account("displayname", "ExamAccount");
&check_existence("/home/workstations/a100/a100pc02");
&ok_account("sambaacctflags","[UX]");
#
&check_account_exists_id("a100pc02");
&check_account_exists_id("a100pc02\$");

# account 3:
%account = &fetch_single_account("uid='b10pc01'");
%account_ldap=&fetch_ldap_account($account{'uid'});
&ok_account("gid", "B10");
&ok_account("adminclass", "B10");
&ok_account("firstname", "Exam");
&ok_account("surname", "Account");
&ok_account("gecos", "ExamAccount");
&ok_account("cn", "ExamAccount");
&ok_account("displayname", "ExamAccount");
&check_existence("/home/workstations/B10/b10pc01");
&ok_account("sambaacctflags","[UX]");
#
&check_account_exists_id("b10pc01");
&check_account_exists_id("b10pc01\$");

# account 4:
%account = &fetch_single_account("uid='b10pc02'");
%account_ldap=&fetch_ldap_account($account{'uid'});
&ok_account("gid", "B10");
&ok_account("adminclass", "B10");
&ok_account("firstname", "Exam");
&ok_account("surname", "Account");
&ok_account("gecos", "ExamAccount");
&ok_account("cn", "ExamAccount");
&ok_account("displayname", "ExamAccount");
&check_existence("/home/workstations/B10/b10pc02");
&ok_account("sambaacctflags","[UX]");
#
&check_account_exists_id("b10pc02");
&check_account_exists_id("b10pc02\$");

# account 5:
# should not exist
&check_account_nonexists_id("printer01");
&check_account_nonexists_id("Printer01");
&check_account_nonexists_id("printer01\$");
&check_account_nonexists_id("Printer01\$");
&check_nonexistence("/home/workstations/printer/printer01");
&check_nonexistence("/home/workstations/printer/Printer01");
&check_nonexistence("/home/workstations/Printer/printer01");
&check_nonexistence("/home/workstations/Printer/Printer01");




print '
###########################################################################
#                                                                         #
#                             REMOVING LINES                              #
#                                                                         #
###########################################################################
';
&remove_line("a100;a100pc01;abc;00:11:22:33:44:01;10.10.1.1;255.240.0.0;1;1;1;1;22;;",
             $ws_file);
&remove_line("a100;a100pc02;abc;00:11:22:33:44:02;10.10.1.2;255.240.0.0;1;1;1;1;22;;",
             $ws_file);
&remove_line("B10;B10PC01;HWK-2;00:11:22:33:44:03;10.10.2.1;255.240.0.0;1;1;1;1;0;;",
             $ws_file);
&remove_line("B10;B10PC02;HWK-2;00:11:22:33:44:04;10.10.2.2;255.240.0.0;1;1;1;1;0;;",
             $ws_file);
&remove_line("Printer;Printer01;prn;00:11:22:33:44:05;10.10.3.1;255.240.0.0;1;1;1;0;0;;",
             $ws_file);



# run sophomorix-workstation
&run_command("sophomorix-workstation --sync-accounts",$verbose);



print '
###########################################################################
#                                                                         #
#                      HOSTS SHOULD NOT EXIST ANYMORE                     #
#                                                                         #
###########################################################################
';
# exam account
&check_account_nonexists_id("a100pc01");
&check_account_nonexists_id("a100pc02");
&check_account_nonexists_id("b10pc01");
&check_account_nonexists_id("b10pc02");
&check_account_nonexists_id("printer01");
&check_account_nonexists_id("Printer01");
&check_nonexistence("/home/workstations/a100/a100pc01");
&check_nonexistence("/home/workstations/a100/a100pc02");
&check_nonexistence("/home/workstations/B10/b10pc01");
&check_nonexistence("/home/workstations/B10/b10pc01");
&check_nonexistence("/home/workstations/b10/b10pc02");
&check_nonexistence("/home/workstations/b10/b10pc02");
&check_nonexistence("/home/workstations/B10/B10PC01");
&check_nonexistence("/home/workstations/B10/B10PC01");
&check_nonexistence("/home/workstations/b10/B10PC02");
&check_nonexistence("/home/workstations/b10/B10PC02");
&check_nonexistence("/home/workstations/printer/printer01");
&check_nonexistence("/home/workstations/printer/Printer01");
&check_nonexistence("/home/workstations/Printer/printer01");
&check_nonexistence("/home/workstations/Printer/Printer01");
# computer account
&check_account_nonexists_id("a100pc01\$");
&check_account_nonexists_id("a100pc02\$");
&check_account_nonexists_id("b10pc01\$");
&check_account_nonexists_id("b10pc02\$");
&check_account_nonexists_id("printer01\$");
&check_account_nonexists_id("Printer01\$");




&log_script_end(@arguments);







###########################################################################
# SUB
###########################################################################



sub check_account_exists_id {
    my ($login) = @_;
    my $result =system("id $login > /dev/null 2>&1");
    is( $result,0, "Account $login exists (id shows account)");
}


sub check_account_nonexists_id {
    my ($login) = @_;
    my $command="id $login > /dev/null 2>&1";
    #print "$command\n";
    my $result =system($command);
    is( $result,256, "Account $login is nonexisting (id shows nothing)");
}





sub ok_account{
    # Hash must be in %account, wich is global in this file
    my ($col, $v) = @_;
    my $ldap_gid;
    my $ldap_cn;
    my $pg_gidnumber;
    my $ldap_gidnumber;

    # pg

    # Make sure that its defined
    if (not defined $account{$col} ){
	$account{$col}="";
    };
    # replace spaces in the sambaaccountflags
    if ($col eq "sambaacctflags"){
       $account{$col}=~s/ //g;
    }
    if ($col eq "creationdate"){
       # use a special regex
       like( $account{$col},qr/^$v.*/, "pgcheck:   $v is $col of $account{uid}");
    } elsif ($col eq "gecos"){
       # check gecos
       is( $account{$col},$v, "pgcheck:   $v is $col of $account{uid}");
       # check cn
       is( $account{'cn'},$v, "pgcheck:   $v is cn of $account{uid}");
       # check description
       # remove whitespace at the end
       my $mod=$account{'description'};
       $mod=~s/\s*$//;
       is( $mod,$v, 
            "pgcheck:   $mod is description of $account{uid}");
    } else {
       # check for equality
       is( $account{$col},$v, "pgcheck:   $v is $col of $account{uid}");
    }

    if ($col eq "gid"){
        # fetch gidnumbers
        $pg_gidnumber=$account{'gidnumber'};
        $ldap_gidnumber=$account_ldap{'gidNumber'};
        # expect ldap to be equal
        is( $pg_gidnumber,$ldap_gidnumber, 
            "gidnums:   ${pg_gidnumber}(pg) = ${ldap_gidnumber}(ldap) of $account_ldap{uid}");

        # fetch gid of ldap
        my $ldap=&Sophomorix::SophomorixPgLdap::auth_connect();

        my ($ldappw,$ldap_rootdn,$dbpw,$suffix,$mail_dom)=
            &Sophomorix::SophomorixPgLdap::fetch_ldap_pg_passwords();
        my $msg = $ldap->search(
            base => "ou=groups,$suffix",
            scope => "sub",
            filter => ("gidNumber=$pg_gidnumber")
        );

        # print $msg->count(), " entries returned\n";
        my $entry = $msg->entry(0);
        ($ldap_cn)=$entry->get_value('cn');
        ($ldap_gid)=$entry->get_value('displayname');

        is( $ldap_cn,$v, 
            "cn:        ${v}(pg->gid) = ${ldap_cn}(ldap->cn) of $account_ldap{uid}");
        is( $ldap_gid,$v, 
            "gid:       ${v}(pg->gid) = ${ldap_gid}(ldap->displayname) of $account_ldap{uid}");
        &Sophomorix::SophomorixPgLdap::auth_disconnect($ldap);
    }

    # ldap
    my $attr;
    
    # key: which pg columns must be checked in ldap
    # value: how is the attribute name in ldap
    my %check= (
          "gecos" => "gecos",
          "homedirectory" => "homeDirectory",
          "displayname" => "displayName",
          "firstname" => "givenName",
          "surname" => "sn",
          "sambahomepath" => "sambaHomePath",
          "sambahomedrive" => "sambaHomeDrive",
          "sambalogontime" => "sambaLogonTime",
          "sambalogofftime" => "sambaLogoffTime",
          "sambakickofftime" => "sambaKickoffTime",
          "sambapwdcanchange" => "sambaPwdCanChange",
          "sambapwdmustchange" => "sambaPwdMustChange",
          "sambaacctflags" => "sambaAcctFlags",
          "sambasid" => "sambaSID",
          "sambaprimarygroupsid" => "sambaPrimaryGroupSID",
          "" => "",
       );

    if (not exists $check{$col}){
	return;
    } else {
        $attr=$check{$col};
    }

    # Make sure that its defined
    if (not defined $account_ldap{$attr} ){
	$account_ldap{$attr}="";
    };
    ## replace spaces in the sambaaccountflags
    #if ($attr eq "sambaacctflags"){
    #   $account_ldap{$attr}=~s/ //g;
    #}

    # check for equality
    is( $account_ldap{$attr},$v, "ldapcheck: $v is $attr of $account_ldap{uid}");

    # check if in cn is the same value as in gecos
    if ($attr eq "gecos"){
        is( $account_ldap{'cn'},$v, "ldapcheck: $v is cn of $account_ldap{uid}");
        is( $account_ldap{'description'},$v, 
                     "ldapcheck: $v is description of $account_ldap{uid}");
    }
}




sub old_ok_account{
    # Hash must be in %account, wich is global in this file
    my ($col, $v) = @_;

    # pg

    # Make sure that its defined
    if (not defined $account{$col} ){
	$account{$col}="";
    };
    # replace spaces in the sambaaccountflags
    if ($col eq "sambaacctflags"){
       $account{$col}=~s/ //g;
    }
    if ($col eq "creationdate"){
       # use a special regex
       like( $account{$col},qr/^$v.*/, "pgcheck: $v is $col of $account{uid}");
    } else {
       # check for equality
       is( $account{$col},$v, "pgcheck: $v is $col of $account{uid}");
    }

    # ldap

    # Make sure that its defined
    if (not defined $account_ldap{$col} ){
	$account_ldap{$col}="";
    };
    # replace spaces in the sambaaccountflags
    if ($col eq "sambaacctflags"){
       $account_ldap{$col}=~s/ //g;
    }
    if ($col eq "creationdate"){
       # use a special regex
       like( $account_ldap{$col},qr/^$v.*/, "ldapcheck: $v is $col of $account_ldap{uid}");
    } else {
       # check for equality
       is( $account_ldap{$col},$v, "ldapcheck: $v is $col of $account_ldap{uid}");
    }
}

