#!/usr/bin/perl use warnings; use strict; use Net::LDAP; use Net::LDAP::LDIF; # delixs-ldap $| = 1; # ungepufferte Ausgabe (in der Policy gefordert) # wir holen uns die Daten use Debconf::Client::ConfModule ':all'; version('2.0'); my ($status1, $status2, $status3, $status4, $status5, $status6, $status7, $status8, $ip, $host, $domain, $ldapbase, $domaene, $smbadmpw, $backend, $backendobjectclass, $rootbindpw, $organization, $dc, $mrc_version, $srv_install); unless (-e "/etc/delixs/delixs_base.conf") { $srv_install = 1; ($status1, $ip) = get('delixs/ip'); ($status2, $host) = get('delixs/host'); ($status3, $domain) = get('delixs/domain'); ($status4, $ldapbase) = get('delixs/ldapbase'); ($status5, $domaene) = get('delixs/domaene'); ($status6, $smbadmpw) = get('delixs/smbadmpw'); } else { $srv_install = 0; $ip = get_delixs_conf('delixs_base.conf', 'ip'); $host = get_delixs_conf('delixs_base.conf', 'host-name'); $domain = get_delixs_conf('delixs_base.conf', 'domain'); $ldapbase = get_delixs_conf('delixs_base.conf', 'ldap-base'); $domaene = get_delixs_conf('delixs_base.conf', 'samba-domain'); $smbadmpw = get_delixs_conf('delixs_base.conf', 'smbadmpw'); } ($status7, $backend) = get('slapd/backend'); ($status8, $organization) = get('shared/organization'); $backend = lc($backend); if ($backend eq 'hdb') { $backendobjectclass='olcHdbConfig'; } else { $backendobjectclass='olcBdbConfig'; } $dc = substr($domain, 0, index($domain,".")); $rootbindpw = &get_pamldap_secret; # save debconf output descriptor: open my $stdout_deb, ">&STDOUT" or die "cannot duplicate stdout: $!"; # reopen stdout to fd 2: open(STDOUT, ">&2"); &debconf_error; if ( defined( $ARGV[0] )) { if ($ARGV[0] eq 'configure') { $mrc_version = $ARGV[1] if ( defined( $ARGV[1] )); # most_recently_configured version &update_ldap_conf; &update_libnss_ldap_conf; &update_nsswitch_conf; &update_pam_ldap_conf; &set_pam_auth; # &get_delixs_acl; &workaround_groups; if ($srv_install == 1) { initialize_ldap(); } else { update_ldap(); } } elsif ($ARGV[0] eq 'abort-upgrade' or $ARGV[0] eq 'abort-remove' or $ARGV[0] eq 'abort-deconfigure') { # da machen wir nichts } else { print STDERR "postinst called with unknown argument $ARGV[0]\n"; exit(1); } } else { print STDERR "postinst called without argument\n"; exit(1); } exit(0); ######## Ende des Hauptprogramms ############ # systemweite Konfiguration für LDAP-Clients: sub update_ldap_conf { my $ldap_conf = '/etc/ldap/ldap.conf'; my (@daten, @daten_org); # wir lesen die /etc/ldap/ldap.conf ein @daten = read_file_content($ldap_conf); @daten_org = @daten; @daten = replace(search => '^\s*BASE', replace => "BASE\t\t$ldapbase", data => \@daten, after => '^#BASE', append => 1); @daten = replace(search => '^\s*URI', replace => "URI\t\tldap://localhost/", data => \@daten, after => '^#URI', append => 1); @daten = replace(search => '^\s*SIZELIMIT', replace => "SIZELIMIT\t3000", data => \@daten, after => '^#SIZELIMIT', append => 1); @daten = replace(search => '^\s*TIMELIMIT', replace => "TIMELIMIT\t15", data => \@daten, after => '^#TIMELIMIT', append => 1); @daten = replace(search => '^\s*DEREF', replace => "DEREF\t\tnever", data => \@daten, after => '^#DEREF', append => 1); # falls Konfiguration geändert wurde, schreiben wir die Aenderungen zurück if ("@daten" ne "@daten_org") { print "Schreibe die Datei $ldap_conf\n"; create_backup($ldap_conf); write_file_content($ldap_conf, @daten); } } sub update_libnss_ldap_conf { my $libnss_ldap_conf = '/etc/libnss-ldap.conf'; my (@daten, @daten_org); # wir lesen die /etc/libnss-ldap.conf ein @daten = read_file_content($libnss_ldap_conf); @daten_org = @daten; @daten = replace(search => '^\s*rootbinddn', replace => "rootbinddn cn=admin,$ldapbase", data => \@daten); @daten = replace(search => '^\s*scope', replace => "scope sub", data => \@daten, after => '^#scope\s+sub'); @daten = replace(search => '^\s*bind_timelimit', replace => "bind_timelimit 30", data => \@daten, after => '^#bind_timelimit\s+30'); @daten = replace(search => '^\s*bind_policy', replace => "bind_policy soft", data => \@daten, after => '^#bind_policy'); @daten = replace(search => '^\s*nss_connect_policy', replace => "nss_connect_policy persist", data => \@daten, after => '^#nss_connect_policy'); # falls Konfiguration geändert wurde, schreiben wir die Aenderungen zurück if ("@daten" ne "@daten_org") { print "Schreibe die Datei $libnss_ldap_conf\n"; create_backup($libnss_ldap_conf); write_file_content($libnss_ldap_conf, @daten); } } sub update_nsswitch_conf { my $nsswitch_conf = '/etc/nsswitch.conf'; my (@daten, @daten_org); # wir lesen die /etc/nsswitch.conf ein @daten = read_file_content($nsswitch_conf); @daten_org = @daten; @daten = replace(search => '^passwd:', replace => "passwd:\t\tfiles ldap", data => \@daten); @daten = replace(search => '^group:', replace => "group:\t\tfiles ldap", data => \@daten); @daten = replace(search => '^shadow:', replace => "shadow:\t\tfiles ldap", data => \@daten); # falls Konfiguration geändert wurde, schreiben wir die Aenderungen zurück if ("@daten" ne "@daten_org") { print "Schreibe die Datei $nsswitch_conf\n"; create_backup($nsswitch_conf); write_file_content($nsswitch_conf, @daten); } } sub update_pam_ldap_conf { my $pam_ldap_conf = '/etc/pam_ldap.conf'; my (@daten, @daten_org); # wir lesen die /etc/pam_ldap.conf ein @daten = read_file_content($pam_ldap_conf); @daten_org = @daten; @daten = replace(search => 'host\s+', replace => "host 127.0.0.1", data => \@daten); @daten = replace(search => '^#scope\s+sub', replace => "scope sub", data => \@daten); @daten = replace(search => '^#bind_policy', replace => "bind_policy soft", data => \@daten); @daten = replace(search => '^#pam_password\s+exop', replace => "pam_password exop", data => \@daten); @daten = replace(search => '^pam_password\s+crypt', replace => "#pam_password crypt", data => \@daten); # falls Konfiguration geändert wurde, schreiben wir die Aenderungen zurück if ("@daten" ne "@daten_org") { print "Schreibe die Datei $pam_ldap_conf\n"; create_backup($pam_ldap_conf); write_file_content($pam_ldap_conf, @daten); } } sub set_pam_auth { print "Aendere libpam-runtime\n"; # restore stdout to debconf: open(STDOUT, ">&", $stdout_deb); # dirty hack to let pam-auth-update accept our preseed configuration system('pam-auth-update --package --remove ldap'); system("sed -i 's/Default: yes/Default: no/' /usr/share/pam-configs/ldap"); set('libpam-runtime libpam-runtime/profiles', 'unix, ldap-no-authtok, smbpasswd-migrate, mkhomedir'); system('pam-auth-update --package --force'); # reopen stdout to fd 2 open(STDOUT, ">&2"); } sub get_delixs_acl { my $acl_file = '/etc/ldap/delixs-acl'; my $text = &get_acls; my @liste = split /\n/, $text; foreach my $zeile (@liste) { $zeile =~ s//$ldapbase/g; $zeile .= "\n"; # Zeilenumbruch anhaengen } # aus der Liste einen String machen (Variable $text wird ueberschrieben) $text = join('', @liste); unless (-f $acl_file) { open DATEI, '>', $acl_file or die "konnte $acl_file nicht zum Schreiben oeffnen!\n"; print DATEI $text; close DATEI; } else { # hier kommen dann Aenderungen an den ACLs rein } } sub create_slapd_conf { my $slapd_conf = '/etc/ldap/slapd.conf'; my (@daten, $schemata, $indizes, $acls, $rootpw, $sizelimit); # erzeuge hash aus aktuellem rootbind-password: my $bindpwhash = `slappasswd -s $rootbindpw 2>&1`; chomp($bindpwhash); $schemata = ""; my @schemata_raw = get_schemata(); foreach my $schema (@schemata_raw) { $schemata .= "include /etc/ldap/schema/".$schema.".schema\n"; } $indizes = ""; my @indizes_raw = get_indizes(); foreach my $index (@indizes_raw) { $indizes .= "index ".$index."\n"; } $acls = ""; my @acls_raw = get_root_acls(); foreach my $acl (@acls_raw) { $acls .= "access $acl \n"; } $rootpw = "rootpw $bindpwhash"; $sizelimit = "3000"; my $C_SUFFIX = $ldapbase; my $C_BACKEND = $backend; my $C_ADMIN = "cn=admin,$ldapbase"; # slapd.conf Vorlage von OpenLDAP holen @daten = (<<"BASE" =~ /([^\n]*\n?)/g); # Global Directives: # Schema and objectClass definitions include /etc/ldap/schema/core.schema include /etc/ldap/schema/cosine.schema include /etc/ldap/schema/nis.schema include /etc/ldap/schema/inetorgperson.schema $schemata # Where the pid file is put. The init.d script # will not stop the server if you change this. pidfile /var/run/slapd/slapd.pid # List of arguments that were passed to the server argsfile /var/run/slapd/slapd.args # Read slapd.conf(5) for possible values loglevel none # The tool-threads parameter sets the actual amount of cpu's that is used # for indexing. tool-threads 1 # The maximum number of entries that is returned for a search operation sizelimit $sizelimit # Where the dynamically loaded modules are stored modulepath /usr/lib/ldap moduleload back_$C_BACKEND ####################################################################### # Specific Backend Directives for $C_BACKEND: # Backend specific directives apply to this backend until another # 'backend' directive occurs backend $C_BACKEND database config rootdn "cn=admin,cn=config" rootpw "$bindpwhash" access to * by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage by * break ####################################################################### # Specific Directives for database #1, of type $C_BACKEND: # Database specific directives apply to this databasse until another # 'database' directive occurs database $C_BACKEND # The base of your directory in database #1 suffix "$C_SUFFIX" # Where the database file are physically stored for database #1 directory "/var/lib/ldap" # Save the time that the entry gets modified, for database #1 lastmod on # Checkpoint the BerkeleyDB database periodically in case of system # failure and to speed slapd shutdown. checkpoint 512 30 # The dbconfig settings are used to generate a DB_CONFIG file the first # time slapd starts. They do NOT override existing an existing DB_CONFIG # file. You should therefore change these settings in DB_CONFIG directly # or remove DB_CONFIG and restart slapd for changes to take effect. # For the Debian package we use 2MB as default but be sure to update this # value if you have plenty of RAM dbconfig set_cachesize 0 2097152 0 # Sven Hartge reported that he had to set this value incredibly high # to get slapd running at all. See http://bugs.debian.org/303057 for more # information. # Number of objects that can be locked at the same time. dbconfig set_lk_max_objects 1500 # Number of locks (both requested and granted) dbconfig set_lk_max_locks 1500 # Number of lockers dbconfig set_lk_max_lockers 1500 # Indexing options for database #1 $indizes # rootdn directive for specifying a superuser on the database. This is needed # for syncrepl. rootdn "cn=admin,$C_SUFFIX" rootpw "$bindpwhash" $acls BASE print "Schreibe die Datei $slapd_conf\n"; write_file_content($slapd_conf, @daten); } # initialize_ldap # wird nur einmal waehrend der Serverinstallation ausgefuehrt sub initialize_ldap { my ($bindpwhash, $anweisung, @daten); # erzeuge hash aus aktuellem rootbind-password: $bindpwhash = `slappasswd -s $rootbindpw 2>&1`; chomp($bindpwhash); # LDAp-Server sicherheitshalber stoppen system('invoke-rc.d slapd stop'); $anweisung = ""; print "Altes LDAP entsorgen\n"; system( "cp -a /etc/ldap/slapd.d /etc/ldap/slapd.d-old" ); system( "rm -rf /var/lib/ldap/* ; rm -rf /etc/ldap/slapd.d/*" ); die "Fehler beim Loeschen \n" if ($? != 0); # initiale ldap.conf erzeugen: create_slapd_conf(); print "Basis-LDAP anlegen\n"; $anweisung = "slaptest -d -1 -f /etc/ldap/slapd.conf -F /etc/ldap/slapd.d > /tmp/slaptest.log 2>&1 \n"; $anweisung .= "chown -R openldap:openldap /etc/ldap/slapd.d\n"; $anweisung .= "chown -R openldap:openldap /var/lib/ldap\n"; $anweisung .= "mv /etc/ldap/slapd.conf /etc/ldap/slapd.conf-init\n"; system( "$anweisung" ); die "Fehler bei Migration \n" if ($? != 0); # Directory Information Tree anlegen: @daten = (<<"DIT" =~ /([^\n]*\n?)/g); dn: $ldapbase objectClass: top objectClass: dcObject objectClass: organization o: $organization dc: $dc dn: cn=admin,$ldapbase objectClass: simpleSecurityObject objectClass: organizationalRole cn: admin description: LDAP administrator userPassword: $bindpwhash DIT my $baseldif = '/tmp/base.ldif'; write_file_content($baseldif, @daten); print "LDAP DIT anlegen\n"; $anweisung = "slapadd -F /etc/ldap/slapd.d -b $ldapbase -l $baseldif \n"; $anweisung .= "chown -R openldap:openldap /etc/ldap/slapd.d\n"; $anweisung .= "chown -R openldap:openldap /var/lib/ldap\n"; system( "$anweisung" ); die "Fehler bei DIR-Anlage \n" if ($? != 0); system("slapcat -l /tmp/ldap-db1.dit"); # OUs anlegen: @daten = create_ou_ldif(); my $ouldif = '/tmp/ou.ldif'; write_file_content($ouldif, @daten); print "Trage delixs-Konfiguration in LDAP ein\n"; $anweisung = "slapadd -l $ouldif \n"; $anweisung .= "chown -R openldap:openldap /etc/ldap/slapd.d \n"; $anweisung .= "chown -R openldap:openldap /var/lib/ldap \n"; system( "$anweisung" ); die "Fehler bei delixs-Zusatz \n" if ($? != 0); print "Re-Indizierung ausfuehren\n"; $anweisung = "slapindex > /tmp/slapindex.log 2>&1 \n"; $anweisung .= "chown -R openldap:openldap /etc/ldap/slapd.d \n"; $anweisung .= "chown -R openldap:openldap /var/lib/ldap \n"; system( "$anweisung" ); die "Fehler bei delixs-Zusatz \n" if ($? != 0); system("slapcat -l /tmp/ldap-db1.delixs"); } # update_ldap # wird bei allen nachfolgenden Updates/Upgrades aufgerufen sub update_ldap { my (@ldap_conf, @ldap_dit, $cmd, $ldap, $mesg); # erzeuge hash aus aktuellem rootbind-password: my $bindpwhash = `slappasswd -s $rootbindpw 2>&1`; chomp($bindpwhash); # sicherstellen, dass LDAP gestartet ist: system('invoke-rc.d slapd start'); # LDAP einlesen: my $ldif = '/tmp/ldap.ldif'; system("slapcat -n 0 -l $ldif"); @ldap_conf = read_file_content($ldif); system("slapcat -n 1 -l $ldif"); @ldap_dit = read_file_content($ldif); # schema erweitern? $ldap = Net::LDAP->new('127.0.0.1', version => 3) or die "update_ldap: ldap->new error: $!\n"; $mesg = $ldap->bind( dn => "cn=admin,cn=config", password => $rootbindpw ) or die "update_ldap: bind error: $! , error: ". $mesg->error. "\n"; my @schemata_raw = get_schemata(); foreach my $schema (@schemata_raw) { # fast solution: # if (! grep /^cn: {\d}$schema/, @ldap_conf) { # add_schema($schema); # } # ldap solution: $mesg = $ldap->search( base => "cn=schema,cn=config", filter => "cn=*".$schema, attrs => ['dn'] ); if ($mesg->count == 0) { add_schema($schema); } } # Indizierung aktualisieren: $mesg = $ldap->search(base => "olcDatabase={1}hdb,cn=config", filter => 'objectclass=*', attrs => ['olcDbIndex'] ); if ($mesg->count > 0) { my $entry = ($mesg->entries)[0]; #my @idx = $entry->get_value('olcDbIndex'); my @indizes_raw = get_indizes(); print "Indizes werden aktualisiert\n"; $mesg = $ldap->modify($entry->dn, replace => { 'olcDbIndex' => \@indizes_raw }); $mesg->code && die("update_ldap: olcDbIndex update error: ", $mesg->error, "\n"); } # ACLs aktualisieren: $mesg = $ldap->search(base => "olcDatabase={1}hdb,cn=config", filter => 'objectclass=*', attrs => ['olcAccess'] ); if ($mesg->count > 0) { my $entry = ($mesg->entries)[0]; my @acls_raw = get_root_acls(); my $cnt = 0; foreach my $acl (@acls_raw) { $acl = "{$cnt}" . $acl; $acl =~ s/\n//g; } print "ACLs werden aktualisiert\n"; $mesg = $ldap->modify($entry->dn, replace => { 'olcAccess' => \@acls_raw }); $mesg->code && die("update_ldap: olcAccess update error: ", $mesg->error, "\n"); } # Konfiguration aktualisieren: $mesg = $ldap->search(base => "olcDatabase={-1}frontend,cn=config", filter => 'objectclass=*', attrs => ['olcSizeLimit'] ); if ($mesg->count > 0) { my $entry = ($mesg->entries)[0]; print "Frontend-Konfiguration wird aktualisiert\n"; $mesg = $ldap->modify($entry->dn, replace => { 'olcSizeLimit' => '3100' }); $mesg->code && die("update_ldap: olcSizeLimit update error: ", $mesg->error, "\n"); } $ldap->unbind; # OUs updaten $ldap = Net::LDAP->new('127.0.0.1', version => 3) or die "update_ldap: ldap->new error: $!\n"; $mesg = $ldap->bind( dn => "cn=admin,$ldapbase", password => $rootbindpw ) or die "update_ldap: bind error: $! , error: ". $mesg->error. "\n"; my @ous = create_ou_dn(); foreach my $ou (@ous) { $mesg = $ldap->search( base => "@$ou[0]", filter => "objectclass=organizationalUnit", attrs => ['cn'] ); if ($mesg->count == 0) { print "organizationalUnit [".@$ou[0]."] wird aufgenommen\n"; $mesg = $ldap->add( dn => "@$ou[0]", attr => [ objectClass => ['top', 'organizationalUnit'], ou => @$ou[2], description => "@$ou[1]" ] ); $mesg->code and die "update_ldap: adding ou [".@$ou[0]."]: $mesg->error"; } } $ldap->unbind; } # add_schema: # bindet neues Schema ins LDAP ein # Schema-Datei muss als LDIF vorliegen sub add_schema { my $schema = shift; my ($ldap, $result, $ldif, $mesg); my $schema_file = "/etc/ldap/schema/$schema.ldif"; if (! -e $schema_file) { die "Schema $schema_file fehlt. Abbruch\n"; } print "Schema $schema wird aufgenommen\n"; # $cmd = "ldapadd -QY EXTERNAL -H ldapi:/// -f $schema_file \n"; # system( "$cmd" ); # die "update_ldap: ldapadd schema $schema \n" if ($? != 0); $ldap = Net::LDAP->new('127.0.0.1', version => 3) or die "add_schema: ldap->new error: $!\n"; $result = $ldap->bind( dn => "cn=admin,cn=config", password => $rootbindpw ) or die "add_schema: bind error: $!\n"; $result->code && die("add_schema: bind error: ", $result->error, "\n"); $ldif = Net::LDAP::LDIF->new($schema_file, "r"); $ldif->{changetype} = 'add'; while (my $change = $ldif->read_entry()) { # print "dn: ", $change->dn, "\n"; my $result = $change->update($ldap); $result->code && die("add_schema: change->update error: ", $result->error, "\n"); if ($result->code) { print STDERR "ldapmodify: ", $result->error, "\n"; last; } # print "\n"; } $ldap->unbind; } # create_ou_ldif # erzeuge aus den gegebenen OUs ein Array im ldif-Format: # dn: ou=groups,$ldapbase # ou: groups # objectClass: top # objectClass: organizationalUnit # description: Container fuer alle Gruppen sub create_ou_ldif { my @ldif = (); my @ous = get_ous(); foreach my $ou (@ous) { if (@{$ou} == 0) { # empty next; } @ldif = (@ldif, create_ou_work('ldif', 0, "$ldapbase", $ou)); } return(@ldif); } # create_ou_dn: # erzeuge aus den gegebenen OUs ein Array aller dn # [ou=groups,$ldapbase], [description of groups], [groups] sub create_ou_dn { my @data = (); my @ous = get_ous(); foreach my $ou (@ous) { if (@{$ou} == 0) { # empty next; } @data = (@data, create_ou_work('dn', 0, "$ldapbase", $ou)); } return(@data); } # create_ou_work # Worker-Funktion, wird von create_ou_xxx gerufen # iteriert rekursiv über alle OUs sub create_ou_work { my $typ = shift; my $level = shift; my $headou = shift; my @ous = @_; my @data = (); foreach my $ou (@ous) { my $subou = "ou=".@$ou[0].",$headou"; if ($typ eq 'ldif') { push (@data, "dn: $subou\n"); push (@data, "ou: @$ou[0]\n"); push (@data, "objectClass: top\n"); push (@data, "objectClass: organizationalUnit\n"); push (@data, "description: @$ou[1]\n\n"); } else { push (@data, [ $subou, @$ou[0], @$ou[1] ] ); } if (scalar(@{$ou->[2]}) > 0) { @data = (@data, create_ou_work($typ, $level+1, $subou, @{$ou->[2]})); } } return(@data); } # get_ous # liefert (mehrdimenionales) Array aller OUs sub get_ous { my @groups = (); my @accnts = ( ["people", "Container fuer alle schul-spezifischen Accounts", [] ], ["machines", "Container der Samba-Maschinen-Accounts", [] ], ); my @ous = ( ["groups", "Container fuer alle Gruppen", [@groups] ], ["accounts", "Container fuer alle Accounts", [@accnts] ], ); return(@ous); } # get_root_acls # liefert Array mit ACL-Direktiven sub get_root_acls { my @acl = ( "to attrs=userPassword\n by self write\n by anonymous auth\n by * none" , "to attrs=shadowLastChange\n by self write\n by anonymous read\n by * none", "to *\n by self write\n by dn=\"cn=admin,$ldapbase\" write\n by * read", ); return(@acl); } # get_schemata # liefert Array mit zusätzlichen LDAP-Schemata sub get_schemata { my @schema = ( "corba", "openldap", "samba", "dhcp", "quota", "sudo", ); return(@schema); } # get_indizes # liefert Array der Index-Direktiven sub get_indizes { my @indizes = ( "objectClass eq", "uidNumber eq", "gidNumber eq", "loginShell eq", "uid eq,pres,sub", "memberUid eq,pres,sub", "uniqueMember eq,pres", "sambaSID eq", "sambaPrimaryGroupSID eq", "sambaGroupType eq", "sambaSIDList eq", "sambaDomainName eq", "displayName eq,sub", "givenName eq,sub", "mail eq,pres,sub", "dhcpHWAddress eq", "dhcpClassData eq", "cn eq,pres,sub", "sn eq,pres,sub", "ou eq", "dc eq", "sudoUser eq", "default sub", ); return(@indizes); } sub workaround_groups { my $gruppe = getgrnam('nvram'); unless (defined($gruppe)) { system('addgroup --system nvram'); } $gruppe = getgrnam('rdma'); unless (defined($gruppe)) { system('addgroup --system rdma'); } $gruppe = getgrnam('kvm'); unless (defined($gruppe)) { system('addgroup --system kvm'); } $gruppe = getgrnam('fuse'); unless (defined($gruppe)) { system('addgroup --system fuse'); } $gruppe = getgrnam('scanner'); unless (defined($gruppe)) { system('addgroup --system scanner'); } $gruppe = getgrnam('tss'); unless (defined($gruppe)) { system('addgroup --system tss'); } my $my_user = getpwnam('tss'); unless (defined($my_user)) { system('adduser --system --no-create-home --ingroup tss tss'); } } # ============== Template für Initialisierung des LDAPs ====================== sub get_acls { my $acls =<<'ENDACLS'; # Inhaber der Rolle "admin" dürfen einfach alles access to * by group/organizationalRole/roleOccupant="cn=admin," manage by * none break # Passwortänderungen access to dn.exact="cn=admin," attrs=userPassword by self write by anonymous auth access to dn.exact="ou=accounts," attrs=children by set="[cn=DomainAdmins,ou=groups,]/memberUid & user/uid" write by set="[cn=hadmins,ou=groups,]/memberUid & user/uid" write by * read access to dn.exact="ou=machines,ou=accounts," attrs=children by set="[cn=DomainAdmins,ou=groups,]/memberUid & user/uid" write by set="[cn=hadmins,ou=groups,]/memberUid & user/uid" write by * read access to dn.exact="ou=people,ou=accounts," attrs=children by set="[cn=DomainAdmins,ou=groups,]/memberUid & user/uid" write by set="[cn=hadmins,ou=groups,]/memberUid & user/uid" write by set="[cn=jadmins,ou=groups,]/memberUid & user/uid" write by set="[cn=tadmins,ou=groups,]/memberUid & user/uid" write by * read access to dn.subtree="ou=people,ou=accounts," attrs=userPassword,sambaLMPassword,sambaNTPassword filter=(&(objectclass=posixAccount)(objectclass=sambaSamAccount)(gidnumber=1002)) by self write by anonymous auth by set="[cn=DomainAdmins,ou=groups,]/memberUid & user/uid" write by set="[cn=hadmins,ou=groups,]/memberUid & user/uid" write by set="[cn=jadmins,ou=groups,]/memberUid & user/uid" write by set="[cn=tadmins,ou=groups,]/memberUid & user/uid" write access to attrs=userPassword,sambaLMPassword,sambaNTPassword by self write by anonymous auth by group/organizationalRole/roleOccupant="cn=admin," manage by set="[cn=DomainAdmins,ou=groups,]/memberUid & user/uid" write by set="[cn=hadmins,ou=groups,]/memberUid & user/uid" write #access to dn.subtree="ou=people,ou=accounts," access to dn.onelevel="ou=people,ou=accounts," attrs=entry,@"extensibleObject" filter=(&(objectclass=posixAccount)(objectclass=sambaSamAccount)(gidnumber=1002)) by set="[cn=DomainAdmins,ou=groups,]/memberUid & user/uid" write by set="[cn=hadmins,ou=groups,]/memberUid & user/uid" write by set="[cn=jadmins,ou=groups,]/memberUid & user/uid" write by set="[cn=tadmins,ou=groups,]/memberUid & user/uid" write by * read access to dn.subtree="ou=people,ou=accounts," by set="[cn=hadmins,ou=groups,]/memberUid & user/uid" write by set="[cn=DomainAdmins,ou=groups,]/memberUid & user/uid" write by * read #access to dn.exact="cn=hadmins,ou=groups," # by dn.exact="uid=root,ou=people,ou=accounts," write # by * read access to dn.exact="cn=jadmins,ou=groups," attrs=memberuid,objectClass by set="[cn=DomainAdmins,ou=groups,]/memberUid & user/uid" write by set="[cn=hadmins,ou=groups,]/memberUid & user/uid" write by * read access to dn.exact="cn=tadmins,ou=groups," attrs=memberuid,objectClass by set="[cn=DomainAdmins,ou=groups,]/memberUid & user/uid" write by set="[cn=hadmins,ou=groups,]/memberUid & user/uid" write by set="[cn=jadmins,ou=groups,]/memberUid & user/uid" write by * read access to dn.subtree="" by set="[cn=hadmins,ou=groups,]/memberUid & user/uid" write by * read access to * by * read ENDACLS return $acls; } # ================ eigene Hilfsfunktionen ==================================== sub debconf_error { if ($status1) { print "\n"; print "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"; print "Couldn't get debconf value for delixs/ip (Status: $status1)\n"; print "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"; print "\n"; } if ($status2) { print "\n"; print "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"; print "Couldn't get debconf value for delixs/host (Status: $status2)\n"; print "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"; print "\n"; } if ($status3) { print "\n"; print "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"; print "Couldn't get debconf value for delixs/domain (Status: $status3)\n"; print "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"; print "\n"; } if ($status4) { print "\n"; print "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"; print "Couldn't get debconf value for delixs/ldapbase (Status: $status4)\n"; print "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"; print "\n"; } if ($status5) { print "\n"; print "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"; print "Couldn't get debconf value for delixs/domaene (Status: $status5)\n"; print "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"; print "\n"; } if ($status6) { print "\n"; print "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"; print "Couldn't get debconf value for delixs/smbadmpw (Status: $status6)\n"; print "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"; print "\n"; } if ($status7) { print "\n"; print "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"; print "Couldn't get debconf value for slapd/backend (Status: $status7)\n"; print "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"; print "\n"; } if ($status8) { print "\n"; print "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"; print "Couldn't get debconf value for shared/organization (Status: $status8)\n"; print "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"; print "\n"; } } # diese Funktion wurde 1:1 aus smbldap-passwd uebernommen sub make_salt { my $length=32; $length = $_[0] if exists($_[0]); my @tab = ('.', '/', 0..9, 'A'..'Z', 'a'..'z'); return join "",@tab[map {rand 64} (1..$length)]; } sub get_pamldap_secret { open DATEI, '<', '/etc/pam_ldap.secret' or die "Abbruch: konnte pam_ldap.secret nicht oeffnen, $!\n"; my $pass = ; close DATEI; chomp($pass); return $pass; } sub replace { # 'data' is an array of lines. # We want to replace an existing or insert a new line into 'data'. # For this we search within all lines for the pattern 'search' and # replace the whole line found with 'replace'. # If pattern was found but 'replace' is set to undef, no replace will occur # If pattern was not found: # if 'replace' is undef, the new line data is given in 'insert' # if 'append' is != 0 we append the new line data at the end of 'data'. # if pattern 'before' or 'after' is set, we search for that in all lines and # prepend or append our new line data to the first one we find. # named arguments: # data : array of lines # search : pattern to search for # replace: string of the replaced/new line (a '\n' gets always appended) # insert: string of the new line(s) if 'replace' is 'undef' (a '\n' gets always appended) # append : '1' if append new line at the end of data array # before : pattern to search for when 'replace' has to be newly inserted # after : pattern to search for when 'replace' has to be newly inserted my (%args) = @_; my %defaults = ( search => "", replace => "", append => 0, before => "", after => "", insert => "" ); %args = (%defaults, %args); my $done = 0; # search line with pattern 'search', replace it with string 'replace': foreach my $line (@{$args{data}}) { if ($line =~ /$args{search}/) { if (defined($args{replace})) { $line = $args{replace} . "\n"; } $done = 1; last; } } if ($done == 0 && !defined($args{replace})) { $args{replace} = $args{insert}; } if ($done == 0 ) { # if not yet done any replacement: if ($done == 0 && ( $args{before} ne "" || $args{after} ne "") ) { # find line 'before' or 'after' and prepend or append new line my $cnt = 0; foreach my $line (@{$args{data}}) { if (($line =~ /$args{after}/) && $args{after} ne "") { splice(@{$args{data}}, $cnt+1, 0, $args{replace} . "\n"); $done = 1; last; } if (($line =~ /$args{before}/) && $args{before} ne "") { splice(@{$args{data}}, $cnt, 0, $args{replace} . "\n"); $done = 1; last; } $cnt++; } # /foreach } # /if before || after if ($done == 0 && $args{append} != 0 ) { # append new line to end of array push @{$args{data}}, $args{replace} . "\n"; $done = 1; } } # /if ! done return @{$args{data}}; } sub create_backup { my ($file, $verbose) = @_; # construct an extension for the backup file: my ($sec,$min,$hour,$day,$mon,$year) = (localtime)[0..5]; my $ext = sprintf ("%04d%02d%02d%02d%02d%02d",$year+1900,$mon+1,$day,$hour,$min,$sec); print "creating backup of file $file to $file.$ext ..." unless ! defined($verbose); my $status = system("cp $file $file.$ext"); die "konnte $file.$ext nicht erzeugen: ". ($? >> 8) ."\n" unless $status == 0; print " success. \n" unless ! defined($verbose); } sub read_file_content { my ($file, $verbose) = @_; my (@content); open (F, "< $file") or die "error opening file $file: $!\n"; @content = ; close (F) or die "error closing file $file: $!\n"; return @content; } sub write_file_content { my ($file, @content) = @_; open (F, "> $file") or die "error opening file $file: $!\n"; print F @content or die "error writing to file $file: $!\n"; close (F) or die "error closing file $file: $!\n"; } sub get_delixs_conf { my $file = shift; my $option = shift; my $value = ''; open DATEI, '<', '/etc/delixs/'.$file or die "konnte $file nicht zum Lesen oeffnen.$!\n"; while () { if ($_ =~ m/^$option=/) { chomp($value = "$'"); last; } } close DATEI; return $value; } __END__