📄 smbldap_tools.pm
字号:
#!/usr/bin/perl -wuse strict;package smbldap_tools;use Net::LDAP;use Crypt::SmbHash;# $Id: smbldap_tools.pm,v 1.62 2005/05/27 14:28:47 jtournier Exp $## This code was developped by IDEALX (http://IDEALX.org/) and# contributors (their names can be found in the CONTRIBUTORS file).## Copyright (C) 2001-2002 IDEALX## 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,# USA.# ugly funcs using global variables and spawning openldap clientsmy $smbldap_conf;if (-e "/etc/smbldap-tools/smbldap.conf") { $smbldap_conf="/etc/smbldap-tools/smbldap.conf";} else { $smbldap_conf="/etc/opt/IDEALX/smbldap-tools/smbldap.conf";}my $smbldap_bind_conf;if (-e "/etc/smbldap-tools/smbldap_bind.conf") { $smbldap_bind_conf="/etc/smbldap-tools/smbldap_bind.conf";} else { $smbldap_bind_conf="/etc/opt/IDEALX/smbldap-tools/smbldap_bind.conf";}my $samba_conf;if (-e "/etc/samba/smb.conf") { $samba_conf="/etc/samba/smb.conf";} else { $samba_conf="/usr/local/samba/lib/smb.conf";}use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);use Exporter;$VERSION = 1.00;@ISA = qw(Exporter);use vars qw(%config $ldap);@EXPORT = qw( get_user_dn get_group_dn is_group_member is_samba_user is_unix_user is_user_valid does_sid_exist get_dn_from_line add_posix_machine add_samba_machine add_samba_machine_smbpasswd group_add_user add_grouplist_user disable_user delete_user group_add group_del get_homedir read_user read_user_entry read_group read_group_entry read_group_entry_gid find_groups_of parse_group group_remove_member group_get_members do_ldapadd do_ldapmodify get_user_dn2 connect_ldap_master connect_ldap_slave group_type_by_name subst_configvar read_config read_parameter subst_user split_arg_comma list_union list_minus get_next_id print_banner getDomainName getLocalSID %config );sub print_banner { print STDERR "(c) Jerome Tournier - IDEALX 2004 (http://www.idealx.com)- Licensed under the GPL\n" unless $config{no_banner}; }sub read_parameter { my $line=shift; ## check for a param = value if ($_=~/=/) { my ($param,$val); if ($_=~/\s*.*?\s*=\s*".*"/) { ($param,$val) = /\s*(.*?)\s*=\s*"(.*)"/; } elsif ($_=~/\s*.*?\s*=\s*'.*'/) { ($param,$val) = /\s*(.*?)\s*=\s*'(.*)'/; } else { ($param,$val) = /\s*(.*?)\s*=\s*(.*)/; } return ($param,$val); } }sub subst_configvar { my $value = shift; my $vars = shift; $value =~ s/\$\{([^}]+)\}/$vars->{$1} ? $vars->{$1} : $1/eg; return $value; }sub read_conf { my %conf; open (CONFIGFILE, "$smbldap_conf") || die "Unable to open $smbldap_conf for reading !\n"; while (<CONFIGFILE>) { chomp($_); ## throw away comments next if ( /^\s*#/ || /^\s*$/ || /^\s*\;/); ## check for a param = value my ($parameter,$value)=read_parameter($_); $value = &subst_configvar($value, \%conf); $conf{$parameter}=$value; } close (CONFIGFILE); if ($< == 0) { open (CONFIGFILE, "$smbldap_bind_conf") || die "Unable to open $smbldap_bind_conf for reading !\n"; while (<CONFIGFILE>) { chomp($_); ## throw away comments next if ( /^\s*#/ || /^\s*$/ || /^\s*\;/); ## check for a param = value my ($parameter,$value)=read_parameter($_); $value = &subst_configvar($value, \%conf); $conf{$parameter}=$value; } close (CONFIGFILE); } else { $conf{slaveDN}=$conf{slavePw}=$conf{masterDN}=$conf{masterPw}=""; } # automatically find SID if (not $conf{SID}) { $conf{SID} = getLocalSID() || die "Unable to determine domain SID: please edit your smbldap.conf, or start your samba server for a few minutes to allow for SID generation to proceed\n"; } return(%conf); }sub read_smbconf { my %conf; my $smbconf="$samba_conf"; open (CONFIGFILE, "$smbconf") || die "Unable to open $smbconf for reading !\n"; my $global=0; while (<CONFIGFILE>) { chomp; if (/^\[global\]/) { $global=1; } if ($global == 1) { if (/^\[/ and !/\[global\]/) { $global=0; } else { ## throw away comments #next if ( ! /workgroup/i ); next if ( /^\s*#/ || /^\s*$/ || /^\s*\;/ || /\[/); ## check for a param = value my ($parameter,$value)=read_parameter($_); $value = &subst_configvar($value, \%conf); $conf{$parameter}=$value; } } } close (CONFIGFILE); return(%conf); }my %smbconf=read_smbconf();sub getLocalSID { my $string = `LANG= PATH=/opt/IDEALX/bin:/usr/local/bin:/usr/bin:/bin net getlocalsid 2>/dev/null`; my ($domain,$sid)=($string =~ m/^SID for domain (\S+) is: (\S+)$/ ); return $sid;}# let's read the configurations file...%config=read_conf();sub get_parameter { # this function return the value for a parameter. The name of the parameter can be either this # defined in smb.conf or smbldap.conf my $parameter_smb=shift; my $parameter_smbldap=shift; if (defined $config{$parameter_smbldap} and $config{$parameter_smbldap} ne "") { return $config{$parameter_smbldap}; } elsif (defined $smbconf{$parameter_smb} and $smbconf{$parameter_smb} ne "") { return $smbconf{$parameter_smb}; } else { #print "could not find parameter's value (parameter given: $parameter_smbldap or $parameter_smb) !!\n"; undef $smbconf{$parameter_smb}; } }$config{sambaDomain}=get_parameter("workgroup","sambaDomain");$config{suffix}=get_parameter("ldap suffix","suffix");$config{usersdn}=get_parameter("ldap user suffix","usersdn");if ($config{usersdn} !~ m/,/ ) {$config{usersdn}=$config{usersdn}.",".$config{suffix};}$config{groupsdn}=get_parameter("ldap group suffix","groupsdn");if ($config{groupsdn} !~ m/,/ ) {$config{groupsdn}=$config{groupsdn}.",".$config{suffix};}$config{computersdn}=get_parameter("ldap machine suffix","computersdn");if ($config{computersdn} !~ m/,/ ) {$config{computersdn}=$config{computersdn}.",".$config{suffix};}$config{idmapdn}=get_parameter("ldap idmap suffix","idmapdn");if (defined $config{idmapdn}) { if ($config{idmapdn} !~ m/,/ ) {$config{idmapdn}=$config{idmapdn}.",".$config{suffix};}}# next uidNumber and gidNumber available are stored in sambaDomainName objectif (!defined $config{sambaUnixIdPooldn}) { $config{sambaUnixIdPooldn}="sambaDomainName=$config{sambaDomain},$config{suffix}";}if (!defined $config{masterLDAP}) { $config{masterLDAP}="127.0.0.1";}if (!defined $config{masterPort}) { $config{masterPort}="389";}if (!defined $config{slaveLDAP}) { $config{slaveLDAP}="127.0.0.1";}if (!defined $config{slavePort}) { $config{slavePort}="389";}if (!defined $config{ldapTLS}) { $config{ldapTLS}="0";}sub connect_ldap_master { # bind to a directory with dn and password my $ldap_master = Net::LDAP->new( "$config{masterLDAP}", port => "$config{masterPort}", version => 3, timeout => 60, # debug => 0xffff, ) or die "erreur LDAP: Can't contact master ldap server ($@)"; if ($config{ldapTLS} == 1) { $ldap_master->start_tls( verify => "$config{verify}", clientcert => "$config{clientcert}", clientkey => "$config{clientkey}", cafile => "$config{cafile}" ); } $ldap_master->bind ( "$config{masterDN}", password => "$config{masterPw}" ); $ldap=$ldap_master; return($ldap_master); }sub connect_ldap_slave { # bind to a directory with dn and password my $conf_cert; my $ldap_slave = Net::LDAP->new( "$config{slaveLDAP}", port => "$config{slavePort}", version => 3, timeout => 60, # debug => 0xffff, ) or warn "erreur LDAP: Can't contact slave ldap server ($@)\n=>trying to contact the master server\n"; if (!$ldap_slave) { # connection to the slave failed: trying to contact the master ... $ldap_slave = Net::LDAP->new( "$config{masterLDAP}", port => "$config{masterPort}", version => 3, timeout => 60, # debug => 0xffff, ) or die "erreur LDAP: Can't contact master ldap server ($@)\n"; } if ($ldap_slave) { if ($config{ldapTLS} == 1) { $ldap_slave->start_tls( verify => "$config{verify}", clientcert => "$config{clientcert}", clientkey => "$config{clientkey}", cafile => "$config{cafile}" ); } $ldap_slave->bind ( "$config{masterDN}", password => "$config{masterPw}" ); $ldap=$ldap_slave; return($ldap_slave); } }sub get_user_dn { my $user = shift; my $dn=''; my $mesg = $ldap->search ( base => $config{suffix}, scope => $config{scope}, filter => "(&(objectclass=posixAccount)(uid=$user))" ); $mesg->code && die $mesg->error; foreach my $entry ($mesg->all_entries) { $dn= $entry->dn; } chomp($dn); if ($dn eq '') { return undef; } $dn="dn: ".$dn; return $dn; }sub get_user_dn2 { my $user = shift; my $dn=''; my $mesg = $ldap->search ( base => $config{suffix}, scope => $config{scope}, filter => "(&(objectclass=posixAccount)(uid=$user))" ); $mesg->code && warn "failed to perform search; ", $mesg->error; foreach my $entry ($mesg->all_entries) { $dn= $entry->dn; } chomp($dn); if ($dn eq '') { return (1,undef); } $dn="dn: ".$dn; return (1,$dn); }sub get_group_dn { my $group = shift; my $dn=''; my $filter; if ($group =~ /^\d+$/) { $filter="(&(objectclass=posixGroup)(|(cn=$group)(gidNumber=$group)))"; } else { $filter="(&(objectclass=posixGroup)(cn=$group))"; } my $mesg = $ldap->search ( base => $config{groupsdn}, scope => $config{scope}, filter => $filter ); $mesg->code && die $mesg->error; foreach my $entry ($mesg->all_entries) { $dn= $entry->dn; } chomp($dn); if ($dn eq '') { return undef; } $dn="dn: ".$dn; return $dn; }# return (success, dn)# bool = is_samba_user($username)sub is_samba_user { my $user = shift; my $mesg = $ldap->search ( base => $config{suffix}, scope => $config{scope}, filter => "(&(objectClass=sambaSamAccount)(uid=$user))" ); $mesg->code && die $mesg->error; return ($mesg->count ne 0); }sub is_unix_user { my $user = shift; my $mesg = $ldap->search ( base => $config{suffix}, scope => $config{scope}, filter => "(&(objectClass=posixAccount)(uid=$user))" ); $mesg->code && die $mesg->error; return ($mesg->count ne 0); }sub is_group_member { my $dn_group = shift; my $user = shift; my $mesg = $ldap->search ( base => $dn_group, scope => 'base', filter => "(&(memberUid=$user))" ); $mesg->code && die $mesg->error; return ($mesg->count ne 0); }# all entries = does_sid_exist($sid,$config{scope})sub does_sid_exist { my $sid = shift; my $dn_group=shift; my $mesg = $ldap->search ( base => $dn_group, scope => $config{scope}, filter => "(sambaSID=$sid)" #filter => "(&(objectClass=sambaSAMAccount|objectClass=sambaGroupMapping)(sambaSID=$sid))" ); $mesg->code && die $mesg->error; return ($mesg); }# try to bind with user dn and password to validate current passwordsub is_user_valid { my ($user, $dn, $pass) = @_; my $userLdap = Net::LDAP->new($config{slaveLDAP}) or die "erreur LDAP"; my $mesg= $userLdap->bind (dn => $dn, password => $pass ); if ($mesg->code eq 0) { $userLdap->unbind; return 1; } else { if ($userLdap->bind()) { $userLdap->unbind; return 0; } else { print ("The LDAP directory is not available.\n Check the server, cables ..."); $userLdap->unbind; return 0; } die "Problem : contact your administrator"; } }# dn = get_dn_from_line ($dn_line)# helper to get "a=b,c=d" from "dn: a=b,c=d"sub get_dn_from_line { my $dn = shift; $dn =~ s/^dn: //; return $dn; }# success = add_posix_machine($user, $uid, $gid)sub add_posix_machine { my ($user,$uid,$gid,$wait) = @_; if (!defined $wait) { $wait=0; } # bind to a directory with dn and password my $add = $ldap->add ( "uid=$user,$config{computersdn}", attr => [ 'objectclass' => ['top','inetOrgPerson', 'posixAccount'], 'cn' => "$user", 'sn' => "$user", 'uid' => "$user", 'uidNumber' => "$uid", 'gidNumber' => "$gid", 'homeDirectory' => '/dev/null', 'loginShell' => '/bin/false', 'description' => 'Computer', 'gecos' => 'Computer', ] ); $add->code && warn "failed to add entry: ", $add->error ; sleep($wait); return 1; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -