diff --git a/contrib/bin/fusiondirectory-setup b/contrib/bin/fusiondirectory-setup deleted file mode 100644 index c240f003f2e537694d491f2ae32f98faaa85a9a6..0000000000000000000000000000000000000000 --- a/contrib/bin/fusiondirectory-setup +++ /dev/null @@ -1,2332 +0,0 @@ -#!/usr/bin/perl - -######################################################################## -# -# fusiondirectory-setup -# -# Manage fusiondirectory installs from the command line -# -# This code is part of FusionDirectory (http://www.fusiondirectory.org/) -# Copyright (C) 2011-2018 FusionDirectory -# -# 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 -# (at your option) 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, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. -# -######################################################################## - -use strict; -use warnings; -use 5.008; - -# used to manage files -use Path::Class; - -# used for checking config dirs rights (make the translation for lstat output) -use Fcntl ':mode'; - -# used to handle ldap connections -use Net::LDAP; - -# used to base64 encode -use MIME::Base64; - -# used to generate {SSHA} password (for LDAP) -use Digest::SHA; -use Crypt::CBC; -use Bytes::Random::Secure qw(random_string_from); - -# used to uncompress tar.gz -use Archive::Extract; - -# used to copy files -use File::Copy::Recursive qw(rcopy); - -#XML parser -use XML::Twig; - -# To hide password input -use Term::ReadKey; - -use Data::Dumper; - -# fd's directory and class.cache file's path declaration -my %vars = ( - fd_home => "/var/www/fusiondirectory", - fd_cache => "/var/cache/fusiondirectory", - fd_config_dir => "/etc/fusiondirectory", - fd_smarty_path => "/usr/share/php/smarty3/Smarty.class.php", - fd_spool_dir => "/var/spool/fusiondirectory", - ldap_conf => "/etc/ldap/ldap.conf", - config_file => "fusiondirectory.conf", - secrets_file => "fusiondirectory.secrets", - locale_dir => "locale", - class_cache => "class.cache", - locale_cache_dir => "locale", - tmp_dir => "tmp", - fai_log_dir => "fai", - template_dir => "template" -); - -my ($fd_config,$fd_secrets,$locale_dir,$class_cache,$locale_cache_dir,$tmp_dir,$fai_log_dir,$template_dir); - -my (@root_config_dirs,@apache_config_dirs,@config_dirs); - -my @plugin_types = qw(addons admin personal); -my $yes_flag = 0; - -my %classes_hash_result = (); -my %i18n_hash_result = (); - -my $configrdn = "cn=config,ou=fusiondirectory"; -my $userrdn = "ou=people"; -my $aclrolerdn = "ou=aclroles"; -my $grouprdn = "ou=groups"; -my $systemrdn = "ou=systems"; -my $dnsrdn = "ou=dns"; -my $dhcprdn = "ou=dhcp"; -my $workstationrdn = "ou=workstations,ou=systems"; -my $winstationrdn = "ou=computers,ou=systems"; - -################################################################################################################################################# - -# ask a question send as parameter, and return true if the answer is "yes" -sub ask_yn_question { - return 1 if ($yes_flag); - my ($question) = @_; - print ( "$question [Yes/No]?\n" ); - - while ( my $input = <STDIN> ) { - # remove the \n at the end of $input - chomp $input; - - # if user's answer is "yes" - if ( lc($input) eq "yes" || lc($input) eq "y") { - return 1; - # else if he answer "no" - } elsif ( lc($input) eq "no" || lc($input) eq "n") { - return 0; - } - } -} - -# function that ask for an user input and do some checks -sub ask_user_input { - my ($thing_to_ask, $default_answer, $hide_input) = @_; - my $answer; - - if (defined $default_answer) { - $thing_to_ask .= " [$default_answer]"; - } - print $thing_to_ask.":\n"; - - if (defined $hide_input && $hide_input) { - ReadMode('noecho'); - } - - do - { - if ($answer = <STDIN>) { - chomp $answer; - $answer =~ s/^\s+|\s+$//g; - } else { - $answer = ""; - } - } while (($answer eq "") && (not defined $default_answer)); - - ReadMode('restore'); - - if ($answer eq "") { - return $default_answer; - } - return $answer; -} - -# Die on all LDAP error except for «No such object» -sub die_on_ldap_errors -{ - my ($mesg) = @_; - if (($mesg->code != 0) && ($mesg->code != 32)) { - die $mesg->error; - } -} - -{ - my $indice = 0; - sub find_free_role_dn { - my ($ldap,$base,$prefix) = @_; - my ($cn,$dn,$mesg); - do { - $cn = $prefix.'-'.$indice; - $dn = "cn=$cn,$aclrolerdn,$base"; - $indice++; - $mesg = $ldap->search( - base => "$dn", - scope => 'base', - filter => '(objectClass=*)' - ); - die_on_ldap_errors($mesg); - } while ($mesg->count); - return $cn; - } -} - -sub create_role { - my ($ldap,$base,$cn,$acl) = @_; - my %role = ( - 'cn' => "$cn", - 'objectclass' => [ 'top', 'gosaRole' ], - 'gosaAclTemplate' => "0:$acl" - ); - - if (!branch_exists($ldap, "$aclrolerdn,$base")) { - create_branch($ldap, $base, $aclrolerdn); - } - - my $role_dn = "cn=$cn,$aclrolerdn,$base"; - # Add the administator role object - my @options = %role; - my $role_add = $ldap->add( $role_dn, attr => \@options ); - # send a warning if the ldap's admin's add didn't gone well - $role_add->code && die "\n! failed to add LDAP's $role_dn entry - ".$role_add->error_name.": ".$role_add->error_text; - return $role_dn; -} - -###################################################### Password encryption ######################################################################### - -sub cred_encrypt { - my ($input, $password) = @_; - my $cipher = Crypt::CBC->new( - -key => $password, - -cipher => 'Rijndael', - -salt => 1, - -header => 'salt', - ) || die "Couldn't create CBC object"; - return $cipher->encrypt_hex($input); -} - -sub cred_decrypt { - my ($input, $password) = @_; - my $cipher = Crypt::CBC->new( - -key => $password, - -cipher => 'Rijndael', - -salt => 1, - -header => 'salt', - ) || die "Couldn't create CBC object"; - return $cipher->decrypt_hex($input); -} - -sub get_random_string { - my ($size) = @_; - $size = 32 if !$size; - my @chars = ("A".."Z", "a".."z", '.', '/', 0..9); - return random_string_from(join('', @chars), $size); -} - -sub encrypt_passwords { - if (!-e $fd_config) { - die "Cannot find a valid configuration file ($fd_config)!\n"; - } - if (-e $fd_secrets) { - die "There's already a file '$fd_secrets'. Cannot convert your existing fusiondirectory.conf - aborted\n"; - } - print "Starting password encryption\n"; - print "* generating random master key\n"; - my $master_key = get_random_string(); - print "* creating '$fd_secrets'\n"; - my $fp_file = file($fd_secrets); - my $fp = $fp_file->openw() or die "! Unable to open '$fd_secrets' in write mode\n"; - $fp->print("RequestHeader set FDKEY $master_key\n"); - $fp->close or die "! Can't close '$fd_secrets'\n"; - chmod 0600, $fd_secrets or die "! Unable to change '$fd_secrets' rights\n"; - my $root_uid = getpwnam("root"); - my $root_gid = getgrnam("root"); - chown $root_uid,$root_gid,$fd_secrets or die "! Unable to change '$fd_secrets' owner\n"; - - # Move original fusiondirectory.conf out of the way and make it unreadable for the web user - print "* creating backup in '$fd_config.orig'\n"; - rcopy($fd_config, "$fd_config.orig"); - chmod 0600, "$fd_config.orig" or die "! Unable to change '$fd_config.orig' rights\n"; - chown $root_uid,$root_gid,"$fd_config.orig" or die "! Unable to change '$fd_config.orig' owner\n"; - - print "* loading '$fd_config'\n"; - my $twig = XML::Twig->new(); # create the twig - $twig->parsefile($fd_config); # build it - # Locate all passwords inside the fusiondirectory.conf - my @locs = $twig->root->first_child('main')->children('location'); - foreach my $loc (@locs) { - my $ref = $loc->first_child('referral'); - print "* encrypting FusionDirectory password for: ".$ref->{'att'}->{'adminDn'}."\n"; - $ref->set_att('adminPassword' => cred_encrypt($ref->{'att'}->{'adminPassword'}, $master_key)); - } - - # Save - print "* saving modified '$fd_config'\n"; - $twig->print_to_file($fd_config, pretty_print => 'indented') or die "Cannot write modified $fd_config - aborted\n"; - print "OK\n\n"; - - # Print reminder - print " -Please adapt your http fusiondirectory declaration to include the newly -created $fd_secrets. - -Example: - -# Include FusionDirectory to your web service -Alias /fusiondirectory $vars{fd_home}/html - -<Directory $vars{fd_home}/html> - # Include the secrects file - include $fd_secrets -</Directory> - - -Please reload your httpd configuration after you've modified anything.\n"; -} - -sub show_passwords { - if (!-e $fd_config) { - die "Cannot find a valid configuration file ($fd_config)!\n"; - } - my $secret; - if (-e $fd_secrets) { - open(my $secrets, q{<}, $fd_secrets) || die ("Could not open $fd_secrets"); - while(<$secrets>) { - if ($_ =~ m/RequestHeader set FDKEY ([^ \n]+)\n/) { - $secret = $1; - last; - } - } - close($secrets); - } - - my $locations = get_locations_from_config_file(); - - while ( my($key,$location) = each %$locations ) { - my ($uri,$base); - if ($location->{'base'} ne '') { - $uri = $location->{'uri'}; - $base = $location->{'base'}; - } elsif ($location->{'uri'} =~ qr|^(.*)/([^/]+)$|) { - # Format from FD<1.3 - $uri = $1; - $base = $2; - } else { - die '"'.$location->{'uri'}.'" does not contain any base!'; - } - my $bind_pwd = $location->{'bind_pwd'}; - if (defined $secret) { - $bind_pwd = cred_decrypt($bind_pwd, $secret); - } - printf("Location \"%s\":\n", $key); - printf(" %-15s%s\n", 'URI', $uri); - printf(" %-15s%s\n", 'Base', $base); - printf(" %-15s%s\n", 'Bind DN', $location->{'bind_dn'}); - printf(" %-15s%s\n", 'Bind password', $bind_pwd); - printf(" %-15s%s\n", 'TLS', $location->{'tls'}); - } -} - -####################################################### class.cache update ######################################################################### - -# function that scan recursivly a directory to find .inc and . php -# then return a hash with class => path to the class file -sub get_classes { - - my ($path) = @_; - - # if this function has been called without a parameter - die ("! function get_classes called without parameter\n") if ( !defined($path) ); - - # create a "dir" object with the path - my $dir = dir ($path) or die ("! Can't open $path\n"); - - my $contrib_dir = dir($vars{fd_home},"contrib"); - if ("$dir" eq "$contrib_dir") { - return; - } - - # create an array with the content of $dir - my @dir_files = $dir->children; - - foreach my $file (@dir_files) { - # recursive call if $file is a directory - if ( -d $file ) { - get_classes($file); - next; - } - - # only process if $file is a .inc or a .php file - if ( ( $file =~ /.*\.inc$/ ) && ( $file !~ /.*smarty.*/ ) ) { - # put the entire content of the file pointed by $file in $data - my @lines = $file->slurp; - - # modifing $file, to contains relative path, not complete one - $file =~ s/^$vars{fd_home}//; - - foreach my $line ( @lines ) { - # remove \n from the end of each line - chomp $line; - - # process for lines beginning with "class", and extracting the 2nd word (the class name) - if ( $line =~ /^(abstract )?class\s*(\w+).*/ ) { - # adding the values (class name and file path) to the hash - $classes_hash_result{$2} = $file; - } - - # process for lines beginning with "interface", and extracting the 2nd word (the interface name) - if ( $line =~ /^interface\s*(\w+).*/ ) { - # adding the values (class name and file path) to the hash - $classes_hash_result{$1} = $file; - } - } - } - } - return %classes_hash_result; -} - -# call get_classes and create /var/cache/fusiondirectory/class.cache -sub rescan_classes { - - # hash that will contain the result of the "get_classes" function - my %get_classes_result = get_classes ($vars{fd_home}); - - # create a "file" object with the $class_cache path - my $file_class = file ($class_cache); - - # create the handler (write mode) for the file previoulsy created - my $fhw = $file_class->openw() or die ("! Unable to open $class_cache in write mode\n"); - - # first lines of class.cache - $fhw->print ("<?php\n\t\$class_mapping= array(\n"); - - # for each $key/$value, writting a new line to $class_cache - while ( my($key,$value) = each %get_classes_result ) { - $fhw->print ("\t\t\"$key\" => \"$value\",\n"); - } - - # last line of classe.cache - $fhw->print ("\t);\n?>"); - - $fhw->close or die ("! Can't close $class_cache\n"); -} - -###################################################### Internalisation's update #################################################################################### - -# function that create .mo files with .po for each language -sub get_i18n { - - my ($path) = @_; - - # if this function has been called without a parameter - die ("! function get_i18n called without parameter" ) if ( !defined($path) ); - - # create a "dir" object - my $dir = dir ($path) or die ("! Can't open $path\n"); - - # create an array with the content of $dir - my @dir_files = $dir->children; - - foreach my $file (@dir_files) { - # recursive call if $file is a directory - if (-d $file) { - %i18n_hash_result = get_i18n ($file); - next; - } - - # if the file's directory is ???/language/fusiondirectory.po - if ($file =~ qr{^.*/(\w+)/fusiondirectory.po$}) { - # push the file's path in the language (fr/en/es/it...) array (wich is inside the hash pointed by $ref_result - push @{$i18n_hash_result{$1}}, $file; - } - } - return %i18n_hash_result; -} - -# call get_i18n with the FusionDirectory's locales's directory and the hash that will contain the result in parameter -sub rescan_i18n { - - # hash that will contain the result of the "get_i18n" function - my %get_i18n_result = get_i18n ($locale_dir); - - while ( my ($lang, $files) = each %get_i18n_result ) { - - # directory wich will contain the .mo file for each language - my $lang_cache_dir = dir ("$locale_cache_dir/$lang/LC_MESSAGES"); - - # if $lang_cache_dir doesn't already exists, creating it - if ( !-d $lang_cache_dir ) { - $lang_cache_dir->mkpath or die ("! Can't create $locale_cache_dir/$lang/LC_MESSAGES"); - } - - # glue .po files's names - my $po_files = join(" ", @{$files}); - chomp $po_files; - - # merging .po files - system ( "msgcat --use-first ".$po_files.">".$lang_cache_dir."/fusiondirectory.po" ) and die ("! Unable to merge .po files for $lang with msgcat, is it already installed?\n"); - - # compiling .po files in .mo files - system ( "msgfmt -o $lang_cache_dir/fusiondirectory.mo $lang_cache_dir/fusiondirectory.po && rm $lang_cache_dir/fusiondirectory.po" ) and die ("! Unable to compile .mo files with msgfmt, is it already installed?\n"); - } -} - -############################################################# Directories checking ################################################################################### - -#get the apache user group name -sub get_apache_group { - my $apache_group = ""; - - # try to identify the running distribution, if it's not debian or rehat like, script ask for user input - if (-e "/etc/debian_version") { - $apache_group = "www-data"; - } elsif ((-e "/etc/redhat-release") || (-e "/etc/mageia-release")) { - $apache_group = "apache"; - } elsif (-e "/etc/SuSE-release") { - $apache_group = "www"; - } elsif (-e "/etc/arch-release") { - $apache_group = "http"; - } else { - print ("! Looks like you are not a Debian, Suse, Redhat or Mageia, I don't know your distribution !\n"); - $apache_group = ask_user_input ("What is your apache group?"); - } - return $apache_group; -} - -#check the rights of a directory or file, creates missing directory if needed -sub check_rights { - my ($dir,$user,$group,$rights,$create) = @_; - my $user_uid = getpwnam ( $user ); - my $group_gid = getgrnam ( $group ); - - # if the current dir exists - if (-e $dir) { - print("$dir exists...\n"); - # retrieve dir's informations - my @lstat = lstat ($dir); - - # extract the owner and the group of the directory - my $dir_owner = getpwuid ( $lstat[4] ); - my $dir_group = getgrgid ( $lstat[5] ); - - # extract the dir's rights - my $dir_rights = S_IMODE( $lstat[2] ); - - if ( ($dir_owner ne $user) || ($dir_group ne $group) || ($dir_rights ne $rights) ) { - if ( ask_yn_question ("$dir is not set properly, do you want to fix it ?: ") ) { - chown ($user_uid,$group_gid,$dir) or die ("! Unable to change $dir owner\n") if ( ($dir_owner ne $user) || ($dir_group ne $group) ); - chmod ( $rights, $dir ) or die ("! Unable to change $dir rights\n") if ($dir_rights ne $rights); - } else { - print ("Skipping...\n"); - } - } else { - print("Rights on $dir are correct\n"); - } - } elsif ($create) { - - if ( ask_yn_question("Directory $dir doesn't exist, do you want to create it ?: ") ) { - my $conf_dir = dir ($dir); - - # create the directory, and change the rights - $conf_dir->mkpath (0,$rights); - chmod ($rights, $dir); - chown ($user_uid,$group_gid,$dir) or die ("Unable to change $dir rights\n"); - - } else { - print ( "Skipping...\n" ); - } - } else { - return 0; - } - return 1; -} - -# function that check FusionDirectory's directories -sub check_directories { - my $apache_group = get_apache_group(); - - # for each config directory - foreach my $dir (@config_dirs) { - - # if $dir is one of the dirs that remains to root - if ( grep (/.*$dir.*/, @root_config_dirs) ) { - check_rights($dir,"root","root",oct(755),1); - - # else if $dir is one of the dirs that remains to apache's user group, and the dir's owner is not root or the group is not the apache's user group, modifying owner - } elsif ( grep ( /.*$dir.*/, @apache_config_dirs) ) { - check_rights($dir,"root",$apache_group,oct(770),1); - } - } -} - -# function that check FusionDirectory's config file -sub check_config { - my $apache_group = get_apache_group(); - - # check config file - check_rights($fd_config,"root",$apache_group,oct(640),0) or die 'The config file does not exist!'; -} - -############################################################# Change install directories ################################################################################# - -sub write_vars { - my $filecontent = <<eof; -<?php -require_once('variables_common.inc'); - -/*! \\file - * Define common locations and variables - * Generated by fusiondirectory-setup */ - -if (!defined("CONFIG_DIR")) { - define ("CONFIG_DIR", "$vars{fd_config_dir}/"); /* FusionDirectory etc path */ -} - -/* Allow setting the config file in the apache configuration - e.g. SetEnv CONFIG_FILE fusiondirectory.conf 1.0 - */ -if (!defined("CONFIG_FILE")) { - define ("CONFIG_FILE", "$vars{config_file}"); /* FusionDirectory filename */ -} - -/* Path for smarty3 libraries */ -define("SMARTY", "$vars{fd_smarty_path}"); - -/* Smarty compile dir */ -define ("SPOOL_DIR", "$vars{fd_spool_dir}/"); /* FusionDirectory spool directory */ - -/* Global cache dir */ -define ("CACHE_DIR", "$vars{fd_cache}/"); /* FusionDirectory var directory */ - -/* Global locale cache dir */ -define ("LOCALE_DIR", "$locale_cache_dir/"); /* FusionDirectory locale directory */ - -/* Global tmp dir */ -define ("TEMP_DIR", "$tmp_dir/"); /* FusionDirectory tmp directory */ - -/* Directory containing the configuration template */ -define ("CONFIG_TEMPLATE_DIR", "$template_dir/"); /* FusionDirectory template directory */ - -/* Directory containing the fai logs */ -define ("FAI_LOG_DIR", "$fai_log_dir/"); /* FusionDirectory fai directory */ - -/* Directory containing the supann files */ -define ("SUPANN_DIR", "$vars{fd_config_dir}/supann/"); /* FusionDirectory supann template directory */ - -/* name of the class.cache file */ -define("CLASS_CACHE", "$vars{class_cache}"); /* name of the class cache */ -?> -eof - - my $variables_path = "$vars{fd_home}/include/variables.inc"; - my $variables_file = file ($variables_path); - my $vars_file = $variables_file->openw() or die ("! Unable to open $variables_path in write mode\n"); - $vars_file->print($filecontent); - $vars_file->close or die ("! Can't close $variables_file\n"); -} - -############################################################# LDAP conformity check ################################################################################# - -# function that add the FusionDirectory's admin account -# return nothing is it a problem? -sub add_ldap_admin { - my ($base, $ldap, $admindns, $people_entries, $roles) = @_; - - # Get the configuration to know which attribute must be used in the dn - my $mesg = $ldap->search( - base => "$configrdn,$base", - filter => '(objectClass=fusionDirectoryConf)', - scope => 'base', - attrs => ['fdAccountPrimaryAttribute', 'fdForcePasswordDefaultHash', 'fdPasswordDefaultHash'] - ); - $mesg->code && die $mesg->error; - my $attr; - if ($mesg->count <= 0) { - print "Could not find configuration object, using default value\n"; - $attr = 'uid'; - } elsif (($mesg->entries)[0]->exists('fdAccountPrimaryAttribute')) { - $attr = ($mesg->entries)[0]->get_value('fdAccountPrimaryAttribute'); - } else { - $attr = 'uid'; - } - if ($mesg->count > 0) { - if (($mesg->entries)[0]->exists('fdForcePasswordDefaultHash') && ($mesg->entries)[0]->exists('fdPasswordDefaultHash')) { - if ((($mesg->entries)[0]->get_value('fdForcePasswordDefaultHash') eq 'TRUE') && - (($mesg->entries)[0]->get_value('fdPasswordDefaultHash') ne 'ssha')) { - warn "Warning: Administrator password will be hashed with ssha instead of forced default ".($mesg->entries)[0]->get_value('fdPasswordDefaultHash')."\n"; - } - } - } - - my $fd_admin_uid = ask_user_input ("Please enter a login for FusionDirectory's admin", "fd-admin"); - # Does this user exist? - my $dn = ""; - foreach my $entry (@$people_entries) { - my $mesg = $ldap->search( - base => "$entry", - filter => "(&(objectClass=inetOrgPerson)(uid=$fd_admin_uid))", - attrs => ['uid'] - ); - $mesg->code && die $mesg->error; - if ($mesg->count) { - print "User $fd_admin_uid already existing, adding admin acl to it\n"; - $dn = ($mesg->entries)[0]->dn; - last; - } - } - - if ($dn eq "") { - my $fd_admin_pwd = ask_user_input ("Please enter FusionDirectory's admin password", undef, 1); - my $fd_admin_pwd_confirm = ask_user_input ("Please enter it again", undef, 1); - - # while the confirmation password is not the same than the first one - while ( ($fd_admin_pwd_confirm ne $fd_admin_pwd) && ($fd_admin_pwd_confirm ne "quit" ) ) { - $fd_admin_pwd_confirm = ask_user_input ("! Inputs don't match, try again or type 'quit' to end this function"); - } - return -1 if ($fd_admin_pwd_confirm eq "quit"); - - my $ctx = Digest::SHA->new(1); - my $salt = get_random_string(8); - $ctx->add($fd_admin_pwd); - $ctx->add($salt); - my $hashedPasswd = '{SSHA}'.encode_base64($ctx->digest.$salt, ''); - my %obj = ( - 'cn' => 'System Administrator', - 'sn' => 'Administrator', - 'uid' => $fd_admin_uid, - 'givenname' => 'System', - 'objectclass' => [ 'top', 'person', 'organizationalPerson', 'inetOrgPerson' ], - 'userPassword' => $hashedPasswd - ); - if (not defined $obj{$attr}) { - print "Error : invalid account primary attribute $attr, using uid\n"; - $attr = 'uid'; - } - $dn = "$attr=".$obj{$attr}.",$userrdn,$base"; - - # Add the administator user object - my @options = %obj; - my $admin_add = $ldap->add( $dn, attr => \@options ); - # send a warning if the ldap's admin's add didn't gone well - $admin_add->code && die "\n! failed to add LDAP's $dn entry - ".$admin_add->error_name.": ".$admin_add->error_text; - } - - # Create admin role if not existing - my $role; - if (scalar @$roles == 0) { - my $role_dn = create_role($ldap,$base,'admin','all;cmdrw'); - $role = encode_base64($role_dn, ''); - } else { - $role = shift(@$roles); - } - - # Add the assignment that make him an administrator - my $acls = $ldap->search ( - base => "$base", - scope => 'base', - filter => "(objectClass=*)", - attrs => ['objectClass', 'gosaAclEntry'] - ); - $acls->code && die "\n! failed to search acls in '$base' - ".$acls->error_name.": ".$acls->error_text; - ($acls->count == 0) && die "\n! failed to search acls in '$base' - base not found"; - my $oclass = ($acls->entries)[0]->get_value("objectClass", asref => 1); - # Add admin acl - my $newacl = ["0:subtree:$role:".encode_base64($dn, '')]; - if (not (grep $_ eq 'gosaAcl', @$oclass)) { - push (@$oclass, 'gosaAcl'); - } else { - my $acl = ($acls->entries)[0]->get_value("gosaAclEntry", asref => 1); - my $i = 1; - if (defined $acl) { - foreach my $line (@$acl) { - # Reorder existing non-admin acls - $line =~ s/^\d+:/$i:/; - push (@$newacl, $line); - $i++; - } - } - } - my $result = $ldap->modify ( - $base, - replace => { - 'objectClass' => $oclass, - 'gosaAclEntry' => $newacl - } - ); - $result->code && warn "\n! failed to add ACL for admin on '$base' - ".$result->error_name.": ".$result->error_text; -} - -sub get_locations_from_config_file -{ - my $twig = XML::Twig->new(); - $twig->safe_parsefile($fd_config) or die("There is an error in $fd_config XML code: ".(split /\n/, $@)[1]."\n"); - my @locs = $twig->root->first_child('main')->children('location'); - my %locations = (); - foreach my $loc (@locs) { - $loc->lc_attnames(); - my $ref = $loc->first_child('referral'); - # Ignore case - $ref->lc_attnames(); - $locations{$loc->{'att'}->{'name'}} = { - 'tls' => 0, - 'uri' => $ref->{'att'}->{'uri'}, - 'base' => ($ref->{'att'}->{'base'} or $loc->{'att'}->{'base'} or ''), - 'bind_dn' => $ref->{'att'}->{'admindn'}, - 'bind_pwd' => $ref->{'att'}->{'adminpassword'} - }; - if (defined $loc->{'att'}->{'ldaptls'} and $loc->{'att'}->{'ldaptls'} =~ m/true/i) { - $locations{$loc->{'att'}->{'name'}}->{'tls'} = 1 - } - } - return \%locations; -} - -# function that initiate the ldap connexion, and bind as the ldap's admin -sub get_ldap_connexion { - my %hash_result = (); - my $bind_dn = ""; - my $bind_pwd = ""; - my $uri = ""; - my $base = ""; - my $tls = 0; - - # read ldap's server's info from /etc/fusiondirectory/fusiondirectory.conf - if (-e $fd_config) { - my $locations = get_locations_from_config_file(); - - my ($location) = keys(%$locations); - if (scalar(keys(%$locations)) > 1) { - my $question = "There are several locations in your config file, which one should be used : (".join(',',keys(%$locations)).")"; - my $answer; - do { - $answer = ask_user_input ($question, $location); - } while (not exists($locations->{$answer})); - $location = $answer; - } - - if ($locations->{$location}->{'base'} ne '') { - $uri = $locations->{$location}->{'uri'}; - $base = $locations->{$location}->{'base'}; - } elsif ($locations->{$location}->{'uri'} =~ qr|^(.*)/([^/]+)$|) { - # Format from FD<1.3 - $uri = $1; - $base = $2; - } else { - die '"'.$locations->{$location}->{'uri'}.'" does not contain any base!'; - } - $bind_dn = $locations->{$location}->{'bind_dn'}; - $bind_pwd = $locations->{$location}->{'bind_pwd'}; - $tls = $locations->{$location}->{'tls'}; - - # if can't find fusiondirectory.conf - } else { - - if ( ask_yn_question ("Can't find fusiondirectory.conf, do you want to specify LDAP's information yourself ?: ") ) { - $uri = ask_user_input ("LDAP server's URI"); - $base = ask_user_input ("Search base"); - $hash_result{base} = $base; - - $bind_dn = ask_user_input ("Bind DN"); - $bind_pwd = ask_user_input("Bind password", undef, 1); - } else { - return; - } - } - - # ldap connection - my $ldap = Net::LDAP->new ($uri) or die ("! Can't contact LDAP server $uri\n"); - - $hash_result{ldap} = $ldap; - $hash_result{base} = $base; - - # bind to the LDAP server - if (-e $fd_secrets) { - open(my $secrets, q{<}, $fd_secrets) || die ("Could not open $fd_secrets"); - my $key = ""; - while(<$secrets>) { - if ($_ =~ m/RequestHeader set FDKEY ([^ \n]+)\n/) { - $key = $1; - last; - } - } - close($secrets); - $bind_pwd = cred_decrypt($bind_pwd, $key); - } - - if ($tls) { - # Read LDAP config file - open (my $ldapconf, q{<}, $vars{ldap_conf}) or die ("! Failed to open ldap config file '$vars{ldap_conf}': $!\n"); - - my %tls_options = ( - 'REQCERT' => 'require', - 'CERT' => '', - 'KEY' => '', - 'CACERTDIR' => '', - 'CACERT' => '', - ); - # Scan LDAP config - while (<$ldapconf>) { - /^\s*(#|$)/ && next; - chomp; - if (m/^TLS_(REQCERT|CERT|KEY|CACERTDIR|CACERT)\s+(.*)\s*$/i) { - $tls_options{uc $1} = $2; - } - } - close($ldapconf); - - $ldap->start_tls( - verify => $tls_options{'REQCERT'}, - clientcert => $tls_options{'CERT'}, - clientkey => $tls_options{'KEY'}, - capath => $tls_options{'CACERTDIR'}, - cafile => $tls_options{'CACERT'} - ); - } - - my $bind = $ldap->bind ($bind_dn, password => $bind_pwd); - - # send a warning if the bind didn't gone well - $bind->code && die ("! Failed to bind to LDAP server: ", $bind->error."\n"); - - return %hash_result; -} - -# function that check if there is an admin -sub check_admin { - my ($base, $ldap, $people_entries) = @_; - - # search for FusionDirectory's admin account - - # search for admin role - my $admin_roles = $ldap->search ( - base => "$base", - filter => "(&(objectClass=gosaRole)(gosaAclTemplate=*:all;cmdrw))", - attrs => ['gosaAclTemplate'] - ); - $admin_roles->code && die $admin_roles->error; - my @dns = (); - my @roles = (); - my $count = 0; - while (my $entry = $admin_roles->shift_entry) { - my $role_dn64 = encode_base64($entry->dn, ''); - push @roles, $role_dn64; - print ("Role ".$entry->dn." is an admin ACL role\n"); - # Search for base-wide assignments - my $assignments = $ldap->search ( - base => "$base", - scope => 'base', - filter => "(&(objectClass=gosaAcl)(gosaAclEntry=*:subtree:$role_dn64:*))", - attrs => ['gosaAclEntry'] - ); - $assignments->code && die $assignments->error; - while (my $assignment = $assignments->shift_entry) { - my $acl = $assignment->get_value("gosaAclEntry", asref => 1); - foreach my $line (@$acl) { - if ($line =~ m/^.:subtree:\Q$role_dn64\E/) { - my @parts = split(':',$line,4); - my @members = split(",",$parts[3]); - foreach my $member (@members) { - # Is this an existing user? - my $dn = decode_base64($member); - my $member_node = $ldap->search( - base => $dn, - scope => 'base', - filter => "(objectClass=inetOrgPerson)" - ); - if ($member_node->count == 1) { - print ("$dn is a valid admin\n"); - return; - } - # Is this a group? - $member_node = $ldap->search( - base => $dn, - scope => 'base', - filter => "(objectClass=posixGroup)", - attrs => ['memberUid'] - ); - if ($member_node->count == 1) { - # Find group members - my $member_entry = $member_node->shift_entry; - my $memberUids = $member_entry->get_value("memberUid", asref => 1); - my $filter = '(&(objectClass=inetOrgPerson)(|(uid='.join(')(uid=', @$memberUids).')))'; - my $group_members = $ldap->search( - base => $base, - filter => $filter, - ); - $group_members->code && die $group_members->error; - if (my $group_member_entry = $group_members->shift_entry) { - print ($group_member_entry->dn." is a valid admin\n"); - return; - } - } else { - push @dns, $dn; - } - } - } - } - } - $count++; - } - if ($count < 1) { - print ("! There is no admin ACL role\n"); - } - foreach my $dn (@dns) { - print ("! $dn is supposed to be admin but does not exist\n"); - } - if (ask_yn_question("No valid admin account found, do you want to create it ?")) { - return add_ldap_admin($base, $ldap, \@dns, $people_entries, \@roles); - } -} - -sub create_branch { - my ($ldap, $base, $ou) = @_; - $ou =~ m/^ou=([^,]*),?$/ or die "Can’t create branch of unknown type $ou\n"; - my $branch_add = $ldap->add( "$ou,$base", - attr => [ - 'ou' => $1, - 'objectClass' => 'organizationalUnit' - ] - ); - - $branch_add->code && die "! failed to add LDAP's $ou,$base branch: ".$branch_add->error."\n"; -} - -sub branch_exists { - my ($ldap, $branch) = @_; - - # search for branch - my $branch_mesg = $ldap->search (base => $branch, filter => '(objectClass=*)', scope => 'base'); - if ($branch_mesg->code == 32) { - return 0; - } - $branch_mesg->code && die $branch_mesg->error; - - my @entries = $branch_mesg->entries; - return (defined ($entries[0])); -} - -# function that check LDAP configuration -sub check_ldap { - # initiate the LDAP connexion - my %hash_ldap_param = get_ldap_connexion(); - - # LDAP's connection's parameters - my $base = $hash_ldap_param{base}; - my $ldap = $hash_ldap_param{ldap}; - - my $admin_add = ""; - - # Collect existing people branches (even if main one may not exists); - my $people = $ldap->search (base => $base, filter => $userrdn); - $people->code && die $people->error; - my @people_entries = $people->entries; - @people_entries = map {$_->dn} @people_entries; - - # if people branch exists - if ( branch_exists($ldap, "$userrdn,$base") ) { - check_admin($base, $ldap, \@people_entries); - - # if ou=people doesn't exist - } else { - print ( "! $userrdn,$base not found in your LDAP directory\n" ); - - # if user's answer is "yes", creating ou=people branch - if ( ask_yn_question("Do you want to create it ?: ") ) { - create_branch($ldap, $base, $userrdn); - push @people_entries, "$userrdn,$base"; - check_admin($base, $ldap, \@people_entries); - } else { - print ("Skipping...\n"); - } - } - - # if groups branch does not exist - if (!branch_exists($ldap, "$grouprdn,$base")) { - print ("! $grouprdn,$base not found in your LDAP directory\n"); - - # if user's answer is "yes", creating groups branch - if ( ask_yn_question("Do you want to create it ?: ") ) { - create_branch($ldap, $base, $grouprdn); - } else { - print ("Skipping...\n"); - } - } - - # search for workstations and object groups - my $faiclasses = $ldap->search (base => "$base", - filter => "(&(FAIclass=*)(!(objectClass~=FAIprofile)))" ); - $faiclasses->code && die $faiclasses->error; - my @faiclass_entries = $faiclasses->entries; - foreach my $entry (@faiclass_entries) { - my $faiclass = $entry->get_value('FAIclass'); - my (@profiles) = split(' ',$faiclass); - if (scalar @profiles > 2) { - print "! System or group ".$entry->get_value('cn')." have more than one FAI profile : ".$faiclass."\n"; - } elsif (scalar @profiles < 2) { - print "! System or group ".$entry->get_value('cn')." have no release set in its FAIclass : ".$faiclass."\n"; - } - } - - # search for old config dn - if (branch_exists($ldap, "cn=fusiondirectory,ou=configs,$base")) { - print ("! There is a configuration in cn=fusiondirectory,ou=configs,$base in your LDAP directory\n"); - print ("! The correct configuration dn is now cn=config,ou=fusiondirectory,$base\n"); - print ("! FusionDirectory will not read your configuration at its current dn\n"); - - if ( ask_yn_question("Do you want to move and rename this entry? ") ) { - if (!branch_exists($ldap, "ou=fusiondirectory,$base")) { - create_branch($ldap, $base, 'ou=fusiondirectory'); - } - my $result = $ldap->moddn ( - "cn=fusiondirectory,ou=configs,$base", - newrdn => 'cn=config', - deleteoldrdn => '1', - newsuperior => "ou=fusiondirectory,$base" - ); - $result->code && die "Migration of configuration entry failed, LDAP error: ".$result->error."\n"; - } else { - print ("Skipping...\n"); - } - } - - - # unbind to the LDAP server - my $unbind = $ldap->unbind; - $unbind->code && warn "! Unable to unbind from LDAP server: ", $unbind->error."\n"; -} - -# function that checks for duplicate uid or gid numbers -sub check_id_numbers { - # initiate the LDAP connexion - my %hash_ldap_param = get_ldap_connexion(); - - # LDAP's connection's parameters - my $ldap = $hash_ldap_param{ldap}; - my $base = $hash_ldap_param{base}; - - check_id_numbers_generic($ldap, $base, 'posixAccount','uidNumber','users'); - - check_id_numbers_generic($ldap, $base, 'posixGroup','gidNumber','groups'); -} - -sub check_id_numbers_generic { - my ($ldap, $base, $objectClass, $attribute, $type) = @_; - - my $mesg = $ldap->search( - filter => "(&(objectClass=$objectClass)($attribute=*))", - base => $base, - attrs => [$attribute] - ); - $mesg->code && die $mesg->error; - - my @entries = $mesg->entries; - - my %tmp = (); - - foreach my $entry (@entries) { - if (not defined $tmp{$entry->get_value($attribute)}) { - $tmp{$entry->get_value($attribute)} = (); - } - push @{$tmp{$entry->get_value($attribute)}}, $entry->dn(); - } - - my $dups = 0; - while (my ($id, $dns) = each %tmp) { - if (scalar(@$dns) > 1) { - $dups = 1; - print "The following $type use the same $attribute $id:\n"; - foreach my $dn (@$dns) { - print "\t$dn\n"; - } - } - } - if ($dups == 0) { - print "There are no duplicate ${attribute}s\n"; - } -} - -# function that create a directory and copy plugin files in it -sub create_and_copy_plugin_dir { - my ($plugin_dir,$dest_dir) = @_; - if ( -e $plugin_dir ){ - my $dir = dir ($dest_dir); - $dir->mkpath() or warn ("! Unable to make ".$dest_dir."\n") if ( !-e $dest_dir); - my $files_dirs_copied = rcopy($plugin_dir."/*", $dest_dir); - } -} - -# function that install all the FD's plugins from a directory -sub install_plugins { - # ask for the plugins archive - my $plugins_archive = ask_user_input ("Where is your plugins archive or folder?"); - die ("! ".$plugins_archive." doesn't exist") if (!-e $plugins_archive); - - my $dir; - if (-d $plugins_archive) { - $dir = dir ($plugins_archive); - } else { - # check the archive format - $plugins_archive =~ /^.*\/(.*).tar.gz$/; - my $name = $1 or die ("! Unknown archive $plugins_archive"); - - # where the extract files will go - my $tmp_plugins_dir = "/tmp"; - - print ("Installing plugins into $vars{fd_home}, please wait...\n"); - - # extract the plugins archive - my $archive = Archive::Extract->new (archive => $plugins_archive); - my $extract = $archive->extract( to => "$tmp_plugins_dir" ) or die ("! Unable to extract $plugins_archive\n"); - - $dir = dir ($tmp_plugins_dir."/".$name); - } - - # List non-hidden children, grep directories, and sort by name - my @plugins = - sort {$a->basename cmp $b->basename} - grep {$_->is_dir} - $dir->children(no_hidden => 1); - - print "Available plugins:\n"; - - my $i = 1; - foreach my $plugin_path (@plugins) { - print $i++.":".$plugin_path->basename."\n"; - } - - my $user_input = ask_user_input("Which plugins do you want to install (use \"all\" to install all plugins)?"); - my @plugins_to_install = split(/\s/, $user_input); - - chdir ($dir) or die ("! Unable to move to $dir\n"); - - $i = 0; - foreach my $plugin_path (@plugins) { - $i++; - - my $plugin = $plugin_path->basename; - - if (grep {($_ eq "all") or ($_ eq $i) or ($_ eq $plugin)} @plugins_to_install) { - print "Installing plugin $plugin\n"; - } else { - next; - } - - # copy addons into plugins - create_and_copy_plugin_dir($plugin_path."/addons/", $vars{fd_home}."/plugins/addons/"); - - # copy admin into plugins - create_and_copy_plugin_dir($plugin_path."/admin/", $vars{fd_home}."/plugins/admin/"); - - # copy config into plugins - create_and_copy_plugin_dir($plugin_path."/config/", $vars{fd_home}."/plugins/config/"); - - # copy personal into plugins - create_and_copy_plugin_dir($plugin_path."/personal/", $vars{fd_home}."/plugins/personal/"); - - # copy extra HTML and images - create_and_copy_plugin_dir($plugin_path."/html/", $vars{fd_home}."/html/"); - - # copy extra theme templates - create_and_copy_plugin_dir($plugin_path."/ihtml/", $vars{fd_home}."/ihtml/"); - - # copy includes - create_and_copy_plugin_dir($plugin_path."/include/", $vars{fd_home}."/include/"); - - # copy ldap schema - create_and_copy_plugin_dir($plugin_path."/contrib/openldap/", $vars{fd_home}."/contrib/openldap/"); - - # copy etc files - create_and_copy_plugin_dir($plugin_path."/contrib/etc/", $vars{fd_config_dir}."/".$plugin."/"); - - # copy doc - create_and_copy_plugin_dir($plugin_path."/contrib/doc/", $vars{fd_home}."/contrib/doc/"); - - # copy the locales - create_and_copy_plugin_dir($plugin_path."/locale/", $vars{fd_home}."/locale/plugins/".$plugin."/locale/"); - } - - #finally update FusionDirectory's class.cache and locales - rescan_classes(); - rescan_i18n(); -} - -# function that add object classes to people branch users -sub migrate_users { - # initiate the LDAP connexion - my %hash_ldap_param = get_ldap_connexion(); - - # LDAP's connection's parameters - my $base = $hash_ldap_param{base}; - my $ldap = $hash_ldap_param{ldap}; - - my $mesg = $ldap->search( - filter => '(&'. - '(|'. - '(objectClass=posixAccount)'. - '(objectClass=person)'. - '(objectClass=OpenLDAPperson)'. - ')'. - '(!(objectClass=ipHost))'. - '(!(objectClass=inetOrgPerson))'. - '(uid=*)'. - ')', - base => $base - ); - $mesg->code && die $mesg->error; - - if ($mesg->count > 0) { - print ("The following users are missing objectClasses:\n"); - - my @entries = $mesg->entries; - - foreach my $entry (@entries) { - print $entry->dn()."\n"; - } - - if (ask_yn_question("Add the inetOrgPerson objectClass to all these entries?")) { - foreach my $entry (@entries) { - $mesg = $ldap->modify($entry->dn(), add => { "objectClass" => ["person","organizationalPerson","inetOrgPerson"]}); - $mesg->code && print $mesg->error."\n"; - } - } - } - - # unbind to the LDAP server - my $unbind = $ldap->unbind; - $unbind->code && warn "! Unable to unbind from LDAP server: ", $unbind->error."\n"; -} - -# function that moves DHCP configurations from systems to ou=dhcp -sub migrate_dhcp { - # initiate the LDAP connexion - my %hash_ldap_param = get_ldap_connexion(); - - # LDAP's connection's parameters - my $base = $hash_ldap_param{base}; - my $ldap = $hash_ldap_param{ldap}; - - # Search for DHCP configurations - my $mesg = $ldap->search( - base => "$base", - filter => "(objectClass=dhcpService)", - attrs => ['cn'] - ); - $mesg->code && die $mesg->error; - - my @entries = $mesg->entries; - - print "There are ".$mesg->count." DHCP configurations in the LDAP\n"; - - my @baddns = (); - - foreach my $entry (@entries) { - if ($entry->dn() !~ m/$dhcprdn/) { - if (scalar(@baddns) == 0) { - print "The following are not in the DHCP branch ($dhcprdn):\n"; - } - print $entry->dn()."\n"; - push @baddns, $entry->dn(); - } - } - - if (scalar(@baddns) == 0) { - print "They all already are in the DHCP branch ($dhcprdn):\n"; - } else { - if (ask_yn_question("Move these entries to the DHCP branch ($dhcprdn)?")) { - foreach my $entrydn (@baddns) { - $entrydn =~ m/^([^,]+),(cn=([^,]+),.*$systemrdn,(.+))$/ or die "Could not parse dn ".$entrydn."\n"; - my $rdn = $1; - my $systemdn = $2; - my $systemcn = $3; - my $entrybase = $4; - if (!branch_exists($ldap, "$dhcprdn,$entrybase")) { - create_branch($ldap, $entrybase, $dhcprdn); - } - my $result = $ldap->moddn ( - $entrydn, - newrdn => "$rdn-$systemcn", - deleteoldrdn => '1', - newsuperior => "$dhcprdn,$entrybase" - ); - $result->code && die "Migration of DHCP configuration entry failed, LDAP error: ".$result->error."\n"; - - my $configDn = "$rdn-$systemcn,$dhcprdn,$entrybase"; - - # Add DHCP service on server - $mesg = $ldap->search( - base => $systemdn, - scope => 'base', - filter => '(objectClass=*)' - ); - $mesg->code && die $mesg->error; - my $system_entry = $mesg->shift_entry; - $system_entry->get_value('objectClass'); - my @classes = $system_entry->get_value('objectClass'); - if (grep {$_ eq 'dhcpServer'} @classes) { - $result = $ldap->modify ( - "$systemdn", - replace => { - 'dhcpServiceDN' => $configDn, - } - ); - } else { - $result = $ldap->modify ( - "$systemdn", - replace => { - 'dhcpServiceDN' => $configDn, - }, - add => { - 'objectClass' => 'dhcpServer' - } - ); - } - $result->code && print "Could not add DHCP service on $systemdn, LDAP error: ".$result->error."\nYou'll need to activate it yourself\n"; - } - } - } -} - -sub delete_gosa_locks { - # initiate the LDAP connexion - my %hash_ldap_param = get_ldap_connexion(); - - # LDAP's connection's parameters - my $base = $hash_ldap_param{base}; - my $ldap = $hash_ldap_param{ldap}; - - # Search for old formatted ACLs - my $mesg = $ldap->search( - base => "$base", - filter => "(objectClass=gosaLockEntry)", - attrs => ['dn'] - ); - $mesg->code && die $mesg->error; - - my @entries = $mesg->entries; - - foreach my $entry (@entries) { - $mesg = $ldap->delete($entry); - if ($mesg->code) { - print "Failed to delete lock '".$entry->dn."': ".$mesg->error."\n"; - } else { - print "Deleted lock '".$entry->dn."'\n"; - } - } -} - -# Get LDAP attributes which have been deprecated -sub get_deprecated { - # initiate the LDAP connexion - my %hash_ldap_param = get_ldap_connexion(); - - # LDAP's connection's parameters - my $base = $hash_ldap_param{base}; - my $ldap = $hash_ldap_param{ldap}; - - my $schema_info = $ldap->schema(); - - my @attributes = $schema_info->all_attributes(); - my @obsolete_attrs = (); - foreach my $attribute (@attributes) { - if ($attribute->{'obsolete'}) { - push @obsolete_attrs, $attribute; - } - } - - my @ocs = $schema_info->all_objectclasses(); - my @obsolete_classes = (); - foreach my $oc (@ocs) { - if ($oc->{'obsolete'}) { - push @obsolete_classes, $oc; - } - } - - return (\@obsolete_attrs, \@obsolete_classes); -} - -# function that migrates systems from FD<1.1 to FD>=1.1 -sub migrate_systems { - # initiate the LDAP connexion - my %hash_ldap_param = get_ldap_connexion(); - - # LDAP's connection's parameters - my $base = $hash_ldap_param{base}; - my $ldap = $hash_ldap_param{ldap}; - - my @oldOCs = ('gotoWorkstation', 'goServer', 'gotoTerminal', 'gotoDevice'); - my @newOCs = ('fdWorkstation', 'fdServer', 'fdTerminal', 'device'); - foreach my $i (0 .. $#oldOCs) { - my $oldOC = $oldOCs[$i]; - my $newOC = $newOCs[$i]; - - my $mesg = $ldap->search( - filter => "(objectClass=$oldOC)", - base => $base - ); - $mesg->code && die $mesg->error; - - if ($mesg->count > 0) { - print ("The following systems are using the obsolete $oldOC objectClass:\n"); - - my @entries = $mesg->entries; - - foreach my $entry (@entries) { - print $entry->dn()."\n"; - } - - if (ask_yn_question("Migrate these entries to $newOC objectClass?")) { - foreach my $entry (@entries) { - my $tmprdn = "cn=".$entry->get_value('cn')."+ipHostNumber=".$entry->get_value('ipHostNumber'); - my $newrdn = "cn=".$entry->get_value('cn'); - my $dn_old = $entry->dn(); - my $dn_new = $entry->dn(); - $dn_new =~ s/^[^,]+,/$tmprdn,/; - $entry->dn($dn_new); - my @replace = ('ieee802Device', 'ipHost', $newOC); - my @classes = $entry->get_value('objectClass'); - foreach my $class (@classes) { - if (($class ne $oldOC) && ($class ne 'GOhard')) { - push(@replace, "$class"); - } - } - $entry->replace("objectClass" => \@replace); - if ($entry->exists('gotoMode')) { - my $gotoMode = $entry->get_value('gotoMode'); - if ($gotoMode eq 'locked') { - $entry->add('fdMode' => 'locked'); - } else { - $entry->add('fdMode' => 'unlocked'); - } - $entry->delete('gotoMode'); - } - if ($entry->exists('argonautLdap2zoneAllowNotify')) { - $entry->delete('argonautLdap2zoneAllowNotify'); - } - $mesg = $ldap->add($entry); - if ($mesg->code) { - print $entry->dn().": ".$mesg->error."\n"; - next; - } - undef @replace; - $mesg = $ldap->delete($dn_old); - if ($mesg->code) { - print $entry->dn().": ".$mesg->error."\n"; - next; - } - $mesg = $ldap->moddn($dn_new, newrdn => $newrdn); - if ($mesg->code) { - print $entry->dn().": ".$mesg->error."\n"; - next; - } - } - } - } else { - print "Found no system using $oldOC\n"; - } - } - - # unbind to the LDAP server - my $unbind = $ldap->unbind; - $unbind->code && warn "! Unable to unbind from LDAP server: ", $unbind->error."\n"; -} - -# function that migrates winstations from FD<1.1 to FD>=1.1 -sub migrate_winstations -{ - # initiate the LDAP connexion - my %hash_ldap_param = get_ldap_connexion(); - - # LDAP's connection's parameters - my $base = $hash_ldap_param{base}; - my $ldap = $hash_ldap_param{ldap}; - - my $mesg = $ldap->search( - filter => "(&(!(objectClass=fdWorkstation))(!(objectClass=inetOrgPerson))(!(objectClass=posixGroup))(uid=*\$)(objectClass=sambaSamAccount))", - base => $base - ); - $mesg->code && die $mesg->error; - - if ($mesg->count > 0) { - print ("The following winstations are not using the new fdWorkstation objectClass:\n"); - - my @entries = $mesg->entries; - - foreach my $entry (@entries) { - print $entry->dn()."\n"; - } - - if (ask_yn_question("Migrate these entries to fdWorkstation objectClass?")) { - foreach my $entry (@entries) { - my $cn = $entry->get_value('cn'); - $cn =~ s/\$$//; - $entry->replace('cn' => $cn); - my $newrdn = "cn=".$cn; - my $dn_old = $entry->dn(); - my $entrybase; - if ($dn_old =~ m/^[^,]+,$winstationrdn,(.+)$/) { - $entrybase = $1; - } elsif ($dn_old =~ m/^[^,]+,.*$systemrdn,(.+)$/) { - $entrybase = $1; - } elsif ($dn_old =~ m/^[^,]+,.*$winstationrdn,(.+)$/) { - $entrybase = $1; - } else { - die "Could not parse dn ".$dn_old."\n"; - } - if (!branch_exists($ldap, "$workstationrdn,$entrybase")) { - if ($workstationrdn =~ m/^([^,]+),([^,]+)$/) { - if (!branch_exists($ldap, "$2,$entrybase")) { - create_branch($ldap, $entrybase, $2); - } - create_branch($ldap, "$2,$entrybase", $1); - } else { - create_branch($ldap, $entrybase, $workstationrdn); - } - } - my $dn_new = "$newrdn,$workstationrdn,$entrybase"; - $entry->dn($dn_new); - my @replace = ('fdWorkstation'); - my @classes = $entry->get_value('objectClass'); - foreach my $class (@classes) { - if ($class ne 'account') { - push(@replace, "$class"); - } - } - $entry->replace("objectClass" => \@replace); - $entry->add('fdMode' => 'unlocked'); - $mesg = $ldap->add($entry); - if ($mesg->code) { - print $entry->dn().": ".$mesg->error."\n"; - next; - } - undef @replace; - $mesg = $ldap->delete($dn_old); - if ($mesg->code) { - print $entry->dn().": ".$mesg->error."\n"; - next; - } - } - } - } else { - print "Found no winstation to migrate\n"; - } -} - -# function that migrates phones from FD<1.1 to FD>=1.1 -sub migrate_phones { - # initiate the LDAP connexion - my %hash_ldap_param = get_ldap_connexion(); - - # LDAP's connection's parameters - my $base = $hash_ldap_param{base}; - my $ldap = $hash_ldap_param{ldap}; - - my $mesg = $ldap->search( - filter => '(&(objectClass=fdPhone)(objectClass=device))', - base => $base - ); - $mesg->code && die $mesg->error; - - if ($mesg->count > 0) { - print ("The following phones are still using the device objectClass:\n"); - - my @entries = $mesg->entries; - - foreach my $entry (@entries) { - print $entry->dn()."\n"; - } - - if (ask_yn_question("Migrate these entries to fdPhone objectClass?")) { - foreach my $entry (@entries) { - my $tmprdn = "cn=".$entry->get_value('cn')."+objectClass=fdPhone"; - my $newrdn = "cn=".$entry->get_value('cn'); - my $dn_old = $entry->dn(); - my $dn_new = $entry->dn(); - $dn_new =~ s/^[^,]+,/$tmprdn,/; - $entry->dn($dn_new); - my @replace = (); - my @classes = $entry->get_value('objectClass'); - foreach my $class (@classes) { - if ($class ne 'device') { - push(@replace, "$class"); - } - } - $entry->replace("objectClass" => \@replace); - $mesg = $ldap->add($entry); - if ($mesg->code) { - print $entry->dn().": ".$mesg->error."\n"; - next; - } - undef @replace; - $mesg = $ldap->delete($dn_old); - if ($mesg->code) { - print $entry->dn().": ".$mesg->error."\n"; - next; - } - $mesg = $ldap->moddn($dn_new, newrdn => $newrdn); - if ($mesg->code) { - print $entry->dn().": ".$mesg->error."\n"; - next; - } - } - } - } - - # unbind to the LDAP server - my $unbind = $ldap->unbind; - $unbind->code && warn "! Unable to unbind from LDAP server: ", $unbind->error."\n"; -} - -# function that migrates interfaces from FD<1.4 to FD>=1.4 -sub migrate_interfaces { - # initiate the LDAP connexion - my %hash_ldap_param = get_ldap_connexion(); - - # LDAP's connection's parameters - my $base = $hash_ldap_param{base}; - my $ldap = $hash_ldap_param{ldap}; - - my @entriesToMigrate = (); - my @entriesToIgnore = (); - - my @systemOCs = ('fdWorkstation', 'fdServer', 'fdTerminal', 'fdPrinter', 'fdPhone', 'fdMobilePhone', 'device'); - - my $mesg = $ldap->search( - filter => "(&(|(objectClass=".join(')(objectClass=', @systemOCs)."))(|(ipHostNumber=*)(macAddress=*)))", - base => $base - ); - $mesg->code && die $mesg->error; - - my @entries = $mesg->entries; - - foreach my $entry (@entries) { - my $mesg2 = $ldap->search( - filter => "(objectClass=fdNetworkInterface)", - base => $entry->dn, - scope => "one" - ); - $mesg2->code && die $mesg2->error; - if ($mesg2->count == 0) { - my @macs = $entry->get_value('macAddress'); - if (scalar(@macs) > 1) { - push @entriesToIgnore, $entry; - next; - } - push @entriesToMigrate, $entry; - } - } - - if (scalar(@entriesToMigrate) > 0) { - print "\nThe following systems are missing an interface node and can be migrated automatically:\n\n"; - foreach my $entry (@entriesToMigrate) { - my @macs = $entry->get_value('macAddress'); - my @ips = $entry->get_value('ipHostNumber'); - print $entry->dn; - if (scalar(@macs) > 0) { - print " with MAC ".join(', ', @macs); - } else { - print " with no MAC"; - } - if (scalar(@ips) > 0) { - print " and IP ".join(', ', @ips)."\n"; - } else { - print " and no IP\n"; - } - } - print "\n"; - - if (ask_yn_question("Migrate these systems by adding an interface node")) { - my $interface_cn = ask_user_input ("Please enter the name for interfaces created by this migration", "eth0"); - my $count = 0; - foreach my $entry (@entriesToMigrate) { - my @macs = $entry->get_value('macAddress'); - my @ips = $entry->get_value('ipHostNumber'); - my %interface = ( - 'cn' => $interface_cn, - 'objectClass' => 'fdNetworkInterface', - ); - - if (scalar(@macs) > 0) { - $interface{'macAddress'} = \@macs; - } - - if (scalar(@ips) > 0) { - $interface{'ipHostNumber'} = \@ips; - } - - my @options = %interface; - my $interface_add = $ldap->add( "cn=$interface_cn,".$entry->dn, attr => \@options ); - - $interface_add->code && die "! failed to add interface: ".$interface_add->error."\n"; - $count++; - } - print $count." entries migrated\n"; - } - } - - if (scalar(@entriesToIgnore) > 0) { - print "\nThe following systems are missing interfaces nodes but cannot be migrated because they have several MAC addresses:\n\n"; - foreach my $entry (@entriesToIgnore) { - my @macs = $entry->get_value('macAddress'); - my @ips = $entry->get_value('ipHostNumber'); - print $entry->dn; - if (scalar(@macs) > 0) { - print " with MAC ".join(', ', @macs); - } else { - print " with no MAC"; - } - if (scalar(@ips) > 0) { - print " and IP ".join(', ', @ips)."\n"; - } else { - print " and no IP\n"; - } - } - print "\n"; - print "Please edit them by hand in FusionDirectory to add interfaces\n"; - } - - if ((scalar(@entriesToMigrate) == 0) and (scalar(@entriesToIgnore) == 0)) { - print "\nNo systems are missing interfaces, nothing to do\n" - } - - print "\n"; - - # unbind to the LDAP server - my $unbind = $ldap->unbind; - $unbind->code && warn "! Unable to unbind from LDAP server: ", $unbind->error."\n"; -} - -# function that removes SupAnn root information from FD<1.4 -sub remove_supann_root { - # initiate the LDAP connexion - my %hash_ldap_param = get_ldap_connexion(); - - # LDAP's connection's parameters - my $base = $hash_ldap_param{base}; - my $ldap = $hash_ldap_param{ldap}; - - my $mesg = $ldap->search( - filter => '(&(objectClass=supannOrg)(objectClass=eduOrg))', - base => $base, - scope => 'one' - ); - $mesg->code && die $mesg->error; - - if ($mesg->count > 0) { - print ("There is an outdated SupAnn establishement stored under root node:\n"); - - my @entries = $mesg->entries; - - foreach my $entry (@entries) { - print $entry->dn()."\n"; - } - - print ("You should remove this entry and check the 'Root establishment' checkbox\n"); - print (" in FusionDirectory to save it in the root node instead.\n"); - - if (ask_yn_question("Remove this entry?")) { - foreach my $entry (@entries) { - $mesg = $ldap->delete($entry); - if ($mesg->code) { - print "Failed to delete entry '".$entry->dn."': ".$mesg->error."\n"; - } else { - print "Deleted entry '".$entry->dn."'\n"; - } - } - } - } else { - print ("There is no outdated SupAnn establishement stored under root node.\n"); - } - - # unbind to the LDAP server - my $unbind = $ldap->unbind; - $unbind->code && warn "! Unable to unbind from LDAP server: ", $unbind->error."\n"; -} - -# List LDAP attributes which have been deprecated -sub list_deprecated { - my ($obsolete_attrs, $obsolete_classes) = get_deprecated(); - - print "Deprecated attributes:\n"; - foreach my $attribute (@$obsolete_attrs) { - printf(" %-30s\t%-60s\t- %s\n", $attribute->{'name'}, '('.$attribute->{'desc'}.')', $attribute->{'oid'}); - } - - print "Deprecated objectClasses:\n"; - foreach my $oc (@$obsolete_classes) { - printf(" %-30s\t%-60s\t- %s\n", $oc->{'name'}, '('.$oc->{'desc'}.')', $oc->{'oid'}); - } -} - -# List LDAP entries using attributes which have been deprecated -sub check_deprecated { - my ($obsolete_attrs, $obsolete_classes) = get_deprecated(); - - my $filterAttrs = '(|'.join('', (map{ '('.$_->{'name'}.'=*)' } @$obsolete_attrs)).')'; - - # initiate the LDAP connexion - my %hash_ldap_param = get_ldap_connexion(); - - # LDAP's connection's parameters - my $base = $hash_ldap_param{base}; - my $ldap = $hash_ldap_param{ldap}; - - my $entries = $ldap->search( - base => "$base", - filter => "$filterAttrs", - ); - $entries->code && die $entries->error; - - if ($entries->count > 0) { - while (my $entry = $entries->shift_entry) { - print $entry->dn." contains an obsolete attribute\n"; - } - } else { - print "There are no entries in the LDAP using obsolete attributes\n"; - } - - my $useobsoletes = 0; - foreach my $class (@$obsolete_classes) { - $entries = $ldap->search( - base => "$base", - filter => '(objectClass='.$class->{'name'}.')', - ); - $entries->code && die $entries->error; - - if ($entries->count > 0) { - $useobsoletes = 1; - while (my $entry = $entries->shift_entry) { - print $entry->dn." uses the obsolete object class ".$class->{'name'}."\n"; - } - } - } - - if (!$useobsoletes) { - print "There are no entries in the LDAP using obsolete classes\n"; - } -} - -# Print a LDIF file removing attributes which have been deprecated -sub ldif_deprecated { - my ($obsolete_attrs, $obsolete_classes) = get_deprecated(); - - my $filterAttrs = '(|'.join('', (map{ '('.$_->{'name'}.'=*)' } @$obsolete_attrs)).')'; - my $filterClasses = '(|'.join('', (map{ '(objectClass='.$_->{'name'}.')' } @$obsolete_classes)).')'; - - # initiate the LDAP connexion - my %hash_ldap_param = get_ldap_connexion(); - - # LDAP's connection's parameters - my $base = $hash_ldap_param{base}; - my $ldap = $hash_ldap_param{ldap}; - - my $entries = $ldap->search( - base => "$base", - filter => "$filterAttrs", - ); - $entries->code && die $entries->error; - - if ($entries->count > 0) { - while (my $entry = $entries->shift_entry) { - print 'dn:'.$entry->dn."\n"; - print "changetype:modify\n"; - foreach my $attr (@$obsolete_attrs) { - if ($entry->exists($attr->{'name'})) { - print "delete:".$attr->{'name'}."\n-\n"; - } - } - print "\n"; - } - } else { - print "# There are no entries in the LDAP using obsolete attributes\n"; - } - - $entries = $ldap->search( - base => "$base", - filter => "$filterClasses", - ); - $entries->code && die $entries->error; - - if ($entries->count > 0) { - print "# WARNING: There are entries in the LDAP using obsolete classes, you need to edit them manually\n"; - } else { - print "# There are no entries in the LDAP using obsolete classes\n"; - } -} - -# Read FD config in the LDAP -sub read_ldap_config { - # initiate the LDAP connexion - my %hash_ldap_param = get_ldap_connexion(); - - # LDAP's connection's parameters - my $base = $hash_ldap_param{base}; - my $ldap = $hash_ldap_param{ldap}; - - my $mesg = $ldap->search (base => "$configrdn,$base", filter => '(objectClass=fusionDirectoryConf)', scope => 'base'); - die_on_ldap_errors($mesg); - - if ($mesg->count > 0) { - if (($mesg->entries)[0]->exists('fdUserRDN')) { - $userrdn = ($mesg->entries)[0]->get_value('fdUserRDN'); - } - if (($mesg->entries)[0]->exists('fdOGroupRDN')) { - $grouprdn = ($mesg->entries)[0]->get_value('fdOGroupRDN'); - } - if (($mesg->entries)[0]->exists('fdAclRoleRDN')) { - $aclrolerdn = ($mesg->entries)[0]->get_value('fdAclRoleRDN'); - } - if (($mesg->entries)[0]->exists('fdSystemRDN')) { - $systemrdn = ($mesg->entries)[0]->get_value('fdSystemRDN'); - } - if (($mesg->entries)[0]->exists('fdDnsRDN')) { - $dnsrdn = ($mesg->entries)[0]->get_value('fdDnsRDN'); - } - if (($mesg->entries)[0]->exists('fdDhcpRDN')) { - $dhcprdn = ($mesg->entries)[0]->get_value('fdDhcpRDN'); - } - if (($mesg->entries)[0]->exists('fdWorkstationRDN')) { - $workstationrdn = ($mesg->entries)[0]->get_value('fdWorkstationRDN'); - } - if (($mesg->entries)[0]->exists('fdSambaMachineAccountRDN')) { - $winstationrdn = ($mesg->entries)[0]->get_value('fdSambaMachineAccountRDN'); - } - } - - return ($mesg->entries)[0]; -} - -sub show_ldap_config { - my $config_node = read_ldap_config(); - $config_node->dump(); -} - -sub set_config_var { - my ($var, $value) = @_; - if (!($var =~ m/^fd/)) { - $var = "fd$var"; - } - - print "Setting configuration var $var to $value\n"; - - # initiate the LDAP connexion - my %hash_ldap_param = get_ldap_connexion(); - - # LDAP's connection's parameters - my $base = $hash_ldap_param{base}; - my $ldap = $hash_ldap_param{ldap}; - - my $result = $ldap->modify ( - "$configrdn,$base", - replace => { - $var => $value - } - ); - $result->code && warn "! failed to set value for '".$var."' - ".$result->error_name.": ".$result->error_text; -} - -sub show_version { - my $variables_common_path = "$vars{fd_home}/include/variables_common.inc"; - if (-e $variables_common_path) { - open(my $vars, q{<}, $variables_common_path) || die ("Could not open $variables_common_path"); - while(<$vars>) { - if ($_ =~ m/^define \(["']FD_VERSION["'], "([^"]+)"\);/) { - print "FusionDirectory version is $1\n"; - last; - } - } - close($vars); - } else { - print "File $variables_common_path does not exist, can’t find out FusionDirectory version\n"; - } -} - -# function that set useful vars based on user specified folders and files -sub set_vars { - $fd_config = $vars{fd_config_dir}."/".$vars{config_file}; - $fd_secrets = $vars{fd_config_dir}."/".$vars{secrets_file}; - $locale_dir = $vars{fd_home}."/".$vars{locale_dir}; - $class_cache = $vars{fd_cache}."/".$vars{class_cache}; - $locale_cache_dir = $vars{fd_cache}."/".$vars{locale_cache_dir}; - $tmp_dir = $vars{fd_cache}."/".$vars{tmp_dir}; - $fai_log_dir = $vars{fd_cache}."/".$vars{fai_log_dir}; - $template_dir = $vars{fd_cache}."/".$vars{template_dir}; - my $supann_dir = $vars{fd_cache}."/supann"; - - @root_config_dirs = ( $vars{fd_home}, $vars{fd_config_dir} ); - @apache_config_dirs = ( $vars{fd_spool_dir}, $vars{fd_cache}, $tmp_dir, $fai_log_dir, - $template_dir ); - @config_dirs = ( @root_config_dirs, @apache_config_dirs ); -} - -# function that list variables that can be modified by the user -sub list_vars { - while ( my ($key, $value) = each(%vars) ) { - print "$key\t[$value]"."\n"; - } -} - -#################### main function ##################### -#die if the user is not root -die ("! You have to run this script as root\n") if ($<!=0); - - my @vars_keys = keys %vars; - - # $commands{<cli-option>} = [<description>, <function>, <needs-ldap-config>]; - my %commands = (); - $commands{"--update-cache"} = ["Updating class.cache", \&rescan_classes]; - $commands{"--update-locales"} = ["Updating translations", \&rescan_i18n]; - $commands{"--check-directories"} = ["Checking FusionDirectory's directories", \&check_directories]; - $commands{"--check-config"} = ["Checking FusionDirectory's config file", \&check_config]; - $commands{"--check-ldap"} = ["Checking your LDAP tree", \&check_ldap, 1]; - $commands{"--check-ids"} = ["Checking for duplicate uid or gid numbers", \&check_id_numbers, 1]; - $commands{"--migrate-users"} = ["Migrating your users", \&migrate_users, 1]; - $commands{"--migrate-phones"} = ["Migrating your phones from FD < 1.1", \&migrate_phones, 1]; - $commands{"--migrate-systems"} = ["Migrating your systems from FD < 1.1", \&migrate_systems, 1]; - $commands{"--migrate-winstations"} = ["Migrating your winstations from FD < 1.1", \&migrate_winstations, 1]; - $commands{"--migrate-dhcp"} = ["Migrating DHCP configurations for FD >= 1.0.17",\&migrate_dhcp, 1]; - $commands{"--migrate-interfaces"} = ["Migrating your systems from FD < 1.4", \&migrate_interfaces, 1]; - $commands{"--remove-supann-root"} = ["Remove SupAnn root establishment from FD < 1.4",\&remove_supann_root, 1]; - $commands{"--delete-gosa-locks"} = ["Delete lock tokens using old gosaLockEntry class", \&delete_gosa_locks]; - $commands{"--install-plugins"} = ["Installing FusionDirectory's plugins", \&install_plugins]; - $commands{"--encrypt-passwords"} = ["Encrypt passwords in fusiondirectory.conf", \&encrypt_passwords]; - $commands{"--show-passwords"} = ["Show passwords from fusiondirectory.conf", \&show_passwords]; - $commands{"--show-version"} = ["Show FusionDirectory version from variables_common.inc", \&show_version]; - $commands{"--list-vars"} = ["List possible vars to give --set", \&list_vars]; - $commands{"--write-vars"} = ["Choose FusionDirectory Directories", \&write_vars]; - $commands{"--set-VAR=value"} = ["Set the variable VAR to value see --list-vars", \&die]; # Won't be called because it contains uppercase - $commands{"--list-deprecated"} = ["List deprecated attributes and objectclasses", \&list_deprecated]; - $commands{"--check-deprecated"} = ["List LDAP entries using deprecated attributes or objectclasses", \&check_deprecated]; - $commands{"--ldif-deprecated"} = ["# Print an LDIF removing deprecated attributes",\&ldif_deprecated]; - $commands{"--show-config"} = ["Show an LDAP dump of the FusionDirectory configuration", \&show_ldap_config]; - $commands{"--set-config-VAR=value"} = ["Set the value in LDAP of a configuration field",\&set_config_var]; - - my $usage = 0; - - set_vars(); - - foreach my $arg ( @ARGV ) { - if (( $arg =~ m/^--set-(.*)=(.*)$/ ) && (grep {$_ eq lc($1)} @vars_keys)) { - $vars{lc($1)} = $2; - print "Setting ".lc($1)." to $2\n"; - set_vars(); - } elsif ( $arg =~ m/^--set-config-(.*)=(.*)$/ ) { - set_config_var($1, $2); - } elsif ( defined $commands { lc ( $arg ) } ) { - my @command = @{ $commands{ $arg } }; - if ((defined $command[2]) && $command[2]) { - read_ldap_config(); - } - print( $command[0]."\n" ); - $command[1](); - } elsif ( ( lc($arg) eq "--help" ) || ( lc($arg) eq "-h" ) ) { - print ( "\nCommands:\n" ); - while ( my ( $key,$value ) = each %commands ) { - print ( "$key\t".$value->[0]."\n" ); - } - print ("--yes\t\t\tAlways answer yes to yes/no questions\n"); - print ("--help\t\t\tShows this help\n\n"); - - } elsif (( lc($arg) eq "--yes" ) || ( lc($arg) eq "-y" )) { - $yes_flag = 1; - } else { - print ("\nInvalid argument\n\n"); - $usage = 1; - } - } - - if( $usage || ( @ARGV <= 0 ) ) { - print ( "Usage : $0 [--yes]" ); - foreach my $command ( keys ( %commands )) { - print ( " [$command]" ); - } - print "\n\n"; - } -exit 0; - -__END__ - -=head1 NAME - -fusiondirectory-setup - FusionDirectory configuration management tool - -=head1 DESCRIPTION - -This script is designed to perform multiple checks on your FusionDirectory/LDAP architecture, and fix usual misconfiguration. -Some extra features allow you to install FusionDirectory's plugins, and change destinations directories. - -=head2 Options - -=over 4 - -=item --update-cache - -This option update the /var/cache/fusiondirectory/class.cache file. Which contain PHP classes used in FusionDirectory, and their location. - -=item --update-locales - -This option update internalization, by generating a new .mo locales file for each language, with every .po files it found. -Needs I<msgcat> and I<msgfmt> to be installed. - -=item --check-directories - -This option perform a check on all FusionDirectory's files or directories. - -=item --check-config - -This option perform a check on FusionDirectory's config file. - -=item --check-ldap - -This option check your LDAP tree. Looking for admin account, and groups or people branch. If one of those doesn't exist, the script will ask you what to do. - -=item --check-ids - -This option check your LDAP tree for duplicate uidNumber or gidNumber among users and groups. - -=item --migrate-users - -This option add FusionDirectory attributes to the people branch. - -=item --migrate-phones - -This option removes device objectClass for phones as fdPhones is now structural since FD 1.1. - -=item --migrate-systems - -This option replace old systems objectClasses by new objectClasses from FD 1.1. - -=item --migrate-winstations - -This option replace old winstations objectClasses by new objectClasses from FD 1.1. - -=item --migrate-dhcp - -This option moves DHCP configurations from systems branch to DHCP branch, which is necessary for FusionDirectory 1.0.17 and above. - -=item --migrate-interfaces - -This option creates interfaces objects for old systems from FD < 1.4. - -=item --delete-gosa-locks - -This option will delete old GOsa style lock tokens from 1.0.15 or older - -=item --install-plugins - -This option will install the plugin from a tar.gz of the plugin. This option is intended for people wanting to install from the sources. - -=item --encrypt-passwords - -This option will encrypt the password inside your fusiondirectory.conf file, it need the headers module to be activated in your apache to work. - -=item --show-passwords - -This option will show the passwords inside your fusiondirectory.conf file as clear text (even if they are encrypted). - -=item --show-version - -This option will parse the file variables_common.inc of FusionDirectory to find out which version of FusionDirectory is installed. - -=item --list_vars - -This option will list the variables you can change to install FusionDirectory on another set of directories. This option is intended for people wanting to install from the sources. - -=item --write-vars - -This option will write back the variables.inc file with the updated variables and is only useful with --set-VAR=variable and for people installing from sources. - -=item --set-VAR=variable - -This option will change the variable for the FusionDirectory installation. it is only useful with --install-directories and for people installing from sources. - -=item --list-deprecated - -This option will list the deprecated attributes and objectclasses still in your schemas and no longer used by FusionDirectory. - -=item --check-deprecated - -This option will list the dn of LDAP entries using deprecated attributes or objectclasses and no longer used by FusionDirectory. - -=item --ldif-deprecated - -This option will print an LDIF to allow you to remove deprecated attributes from you ldap server. Be careful and check before applying. - -=item --show-config - -This option will print a dump of the FusionDirectory configuration LDAP node. - -=item --set-config-VAR=value - -This option sets the value of a configuration field in the LDAP. The value needs to be in the correct LDAP format. -You cannot set multivalued field with this. The var name can be provided with or without the fd prefix. - -=item --yes - -This flag will answer "yes" to every yes/no question asked by the script - -=back - -=head1 EXAMPLE - - benoit@catbert$ fusiondirectory-setup --update-cache --update-locales - - Update FusionDirectory class cache and update localization - - benoit@catbert$ fusiondirectory-setup --list-vars - List possible vars to give --set -locale_cache_dir [locale] -config_file [fusiondirectory.conf] -fd_cache [/var/cache/fusiondirectory] -fd_smarty_path [/usr/share/php/smarty3/Smarty.class.php] -fd_spool_dir [/var/spool/fusiondirectory] -fai_log_dir [fai] -tmp_dir [tmp] -secrets_file [fusiondirectory.secrets] -template_dir [template] -locale_dir [locale] -class_cache [class.cache] -fd_config_dir [/etc/fusiondirectory] -fd_home [/var/www/fusiondirectory] - - - benoit@catbert$ fusiondirectory-setup --set-class_cache=class.cache --write-vars - - update the class.cache name and write back the variables.inc file - -=head1 BUGS - -Please report any bugs, or post any suggestions, to the fusiondirectory mailing list fusiondirectory-users or to -<https://gitlab.fusiondirectory.org/fusiondirectory/fd/issues/new> - -=head1 AUTHORS - -Benjamin Carpentier - -Come Bernigaud - -=head1 LICENCE AND COPYRIGHT - -This code is part of FusionDirectory (http://www.fusiondirectory.org/) - -=over 2 - -=item Copyright (C) 2011-2018 FusionDirectory - -=back - -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. - -=cut