cloud-mu 3.6.9 → 3.6.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Berksfile +2 -3
- data/Berksfile.lock +11 -14
- data/bin/mu-aws-setup +16 -4
- data/bin/mu-configure +2 -1
- data/cloud-mu.gemspec +2 -2
- data/cookbooks/mu-firewall/Berksfile +1 -1
- data/cookbooks/mu-firewall/attributes/default.rb +2 -2
- data/cookbooks/mu-firewall/metadata.rb +3 -3
- data/cookbooks/mu-firewall/recipes/default.rb +11 -2
- data/cookbooks/mu-master/Berksfile +1 -1
- data/cookbooks/mu-master/attributes/default.rb +14 -1
- data/cookbooks/mu-master/files/default/389ds-perl/ASDialogs.pm +173 -0
- data/cookbooks/mu-master/files/default/389ds-perl/AdminMigration.pm +569 -0
- data/cookbooks/mu-master/files/default/389ds-perl/AdminServer.pm +952 -0
- data/cookbooks/mu-master/files/default/389ds-perl/AdminUtil.pm +983 -0
- data/cookbooks/mu-master/files/default/389ds-perl/ConfigDSDialogs.pm +449 -0
- data/cookbooks/mu-master/files/default/389ds-perl/DSCreate.pm +1551 -0
- data/cookbooks/mu-master/files/default/389ds-perl/DSDialogs.pm +233 -0
- data/cookbooks/mu-master/files/default/389ds-perl/DSMigration.pm +1175 -0
- data/cookbooks/mu-master/files/default/389ds-perl/DSUpdate.pm +534 -0
- data/cookbooks/mu-master/files/default/389ds-perl/DSUpdateDialogs.pm +152 -0
- data/cookbooks/mu-master/files/default/389ds-perl/DSUtil.pm +1710 -0
- data/cookbooks/mu-master/files/default/389ds-perl/Dialog.pm +249 -0
- data/cookbooks/mu-master/files/default/389ds-perl/DialogManager.pm +212 -0
- data/cookbooks/mu-master/files/default/389ds-perl/FileConn.pm +461 -0
- data/cookbooks/mu-master/files/default/389ds-perl/Inf.pm +268 -0
- data/cookbooks/mu-master/files/default/389ds-perl/Migration.pm +327 -0
- data/cookbooks/mu-master/files/default/389ds-perl/RegDSDialogs.pm +94 -0
- data/cookbooks/mu-master/files/default/389ds-perl/Resource.pm +137 -0
- data/cookbooks/mu-master/files/default/389ds-perl/Setup.pm +240 -0
- data/cookbooks/mu-master/files/default/389ds-perl/SetupDialogs.pm +243 -0
- data/cookbooks/mu-master/files/default/389ds-perl/SetupLog.pm +82 -0
- data/cookbooks/mu-master/files/default/setCertName.ldif +4 -0
- data/cookbooks/mu-master/libraries/mu.rb +2 -2
- data/cookbooks/mu-master/metadata.rb +1 -1
- data/cookbooks/mu-master/recipes/389ds.rb +71 -32
- data/cookbooks/mu-master/recipes/basepackages.rb +5 -0
- data/cookbooks/mu-master/recipes/default.rb +16 -5
- data/cookbooks/mu-master/recipes/init.rb +59 -4
- data/cookbooks/mu-master/recipes/ssl-certs.rb +6 -0
- data/cookbooks/mu-master/recipes/sssd.rb +85 -62
- data/cookbooks/mu-master/recipes/update_nagios_only.rb +7 -1
- data/cookbooks/mu-master/templates/default/389-directory-setup.inf.erb +11 -26
- data/cookbooks/mu-master/templates/default/sssd.conf.erb +18 -8
- data/cookbooks/mu-tools/files/default/Mu_CA.pem +33 -0
- data/cookbooks/mu-tools/metadata.rb +0 -1
- data/cookbooks/mu-tools/recipes/set_local_fw.rb +7 -1
- data/cookbooks/mu-tools/templates/amazon/sshd_config.erb +5 -1
- data/cookbooks/nagios/CHANGELOG.md +679 -0
- data/cookbooks/nagios/LICENSE +201 -0
- data/cookbooks/nagios/README.md +340 -0
- data/cookbooks/nagios/attributes/config.rb +163 -0
- data/cookbooks/nagios/attributes/default.rb +204 -0
- data/cookbooks/nagios/libraries/base.rb +311 -0
- data/cookbooks/nagios/libraries/command.rb +68 -0
- data/cookbooks/nagios/libraries/contact.rb +229 -0
- data/cookbooks/nagios/libraries/contactgroup.rb +111 -0
- data/cookbooks/{firewall/recipes/disable_firewall.rb → nagios/libraries/custom_option.rb} +20 -7
- data/cookbooks/nagios/libraries/data_bag_helper.rb +23 -0
- data/cookbooks/nagios/libraries/default.rb +90 -0
- data/cookbooks/nagios/libraries/helpers.rb +229 -0
- data/cookbooks/nagios/libraries/host.rb +410 -0
- data/cookbooks/nagios/libraries/hostdependency.rb +178 -0
- data/cookbooks/nagios/libraries/hostescalation.rb +170 -0
- data/cookbooks/nagios/libraries/hostgroup.rb +117 -0
- data/cookbooks/nagios/libraries/nagios.rb +277 -0
- data/cookbooks/nagios/libraries/resource.rb +59 -0
- data/cookbooks/nagios/libraries/service.rb +449 -0
- data/cookbooks/nagios/libraries/servicedependency.rb +213 -0
- data/cookbooks/nagios/libraries/serviceescalation.rb +193 -0
- data/cookbooks/nagios/libraries/servicegroup.rb +142 -0
- data/cookbooks/nagios/libraries/timeperiod.rb +159 -0
- data/cookbooks/nagios/libraries/users_helper.rb +54 -0
- data/cookbooks/nagios/metadata.json +44 -0
- data/cookbooks/nagios/metadata.rb +22 -0
- data/cookbooks/nagios/recipes/_load_databag_config.rb +153 -0
- data/cookbooks/nagios/recipes/_load_default_config.rb +241 -0
- data/cookbooks/nagios/recipes/apache.rb +114 -0
- data/cookbooks/nagios/recipes/default.rb +41 -0
- data/cookbooks/nagios/recipes/nginx.rb +114 -0
- data/cookbooks/nagios/recipes/pagerduty.rb +95 -0
- data/cookbooks/nagios/recipes/server.rb +182 -0
- data/cookbooks/nagios/recipes/server_package.rb +85 -0
- data/cookbooks/nagios/recipes/server_source.rb +137 -0
- data/cookbooks/nagios/resources/command.rb +34 -0
- data/cookbooks/nagios/resources/conf.rb +52 -0
- data/cookbooks/nagios/resources/contact.rb +34 -0
- data/cookbooks/nagios/resources/contactgroup.rb +35 -0
- data/cookbooks/nagios/resources/host.rb +35 -0
- data/cookbooks/nagios/resources/hostdependency.rb +35 -0
- data/cookbooks/nagios/resources/hostescalation.rb +36 -0
- data/cookbooks/nagios/resources/hostgroup.rb +35 -0
- data/cookbooks/nagios/resources/resource.rb +34 -0
- data/cookbooks/nagios/resources/service.rb +35 -0
- data/cookbooks/nagios/resources/servicedependency.rb +35 -0
- data/cookbooks/nagios/resources/serviceescalation.rb +35 -0
- data/cookbooks/nagios/resources/servicegroup.rb +35 -0
- data/cookbooks/nagios/resources/timeperiod.rb +35 -0
- data/cookbooks/nagios/templates/apache2.conf.erb +102 -0
- data/cookbooks/nagios/templates/cgi.cfg.erb +266 -0
- data/cookbooks/nagios/templates/commands.cfg.erb +13 -0
- data/cookbooks/nagios/templates/contacts.cfg.erb +37 -0
- data/cookbooks/nagios/templates/hostgroups.cfg.erb +25 -0
- data/cookbooks/nagios/templates/hosts.cfg.erb +15 -0
- data/cookbooks/nagios/templates/htpasswd.users.erb +6 -0
- data/cookbooks/nagios/templates/nagios.cfg.erb +22 -0
- data/cookbooks/nagios/templates/nginx.conf.erb +80 -0
- data/cookbooks/nagios/templates/pagerduty.cgi.erb +185 -0
- data/cookbooks/nagios/templates/resource.cfg.erb +27 -0
- data/cookbooks/nagios/templates/servicedependencies.cfg.erb +15 -0
- data/cookbooks/nagios/templates/servicegroups.cfg.erb +14 -0
- data/cookbooks/nagios/templates/services.cfg.erb +14 -0
- data/cookbooks/nagios/templates/spawn-fcgi.erb +10 -0
- data/cookbooks/nagios/templates/templates.cfg.erb +31 -0
- data/cookbooks/nagios/templates/timeperiods.cfg.erb +13 -0
- data/extras/platform_berksfile_base +3 -3
- data/extras/python_rpm/build.sh +4 -4
- data/extras/python_rpm/muthon.spec +2 -4
- data/extras/vault_tools/export_vaults.sh +11 -1
- data/install/installer +1 -1
- data/modules/mu/kittens.rb +27523 -0
- data/modules/mu/master/ldap.rb +48 -31
- data/modules/mu/master.rb +69 -0
- data/modules/mu/mu.yaml.rb +351 -0
- data/modules/mu/providers/aws/firewall_rule.rb +3 -1
- data/modules/mu/providers/aws.rb +27 -19
- data/modules/mu/providers/google.rb +1 -1
- data/modules/mu.rb +5 -4
- metadata +99 -48
- data/cookbooks/firewall/CHANGELOG.md +0 -488
- data/cookbooks/firewall/LICENSE +0 -202
- data/cookbooks/firewall/README.md +0 -366
- data/cookbooks/firewall/TODO.md +0 -6
- data/cookbooks/firewall/attributes/default.rb +0 -5
- data/cookbooks/firewall/attributes/firewalld.rb +0 -8
- data/cookbooks/firewall/attributes/iptables.rb +0 -17
- data/cookbooks/firewall/attributes/ufw.rb +0 -12
- data/cookbooks/firewall/attributes/windows.rb +0 -8
- data/cookbooks/firewall/libraries/helpers.rb +0 -105
- data/cookbooks/firewall/libraries/helpers_firewalld.rb +0 -116
- data/cookbooks/firewall/libraries/helpers_firewalld_dbus.rb +0 -72
- data/cookbooks/firewall/libraries/helpers_iptables.rb +0 -112
- data/cookbooks/firewall/libraries/helpers_nftables.rb +0 -170
- data/cookbooks/firewall/libraries/helpers_ufw.rb +0 -142
- data/cookbooks/firewall/libraries/helpers_windows.rb +0 -129
- data/cookbooks/firewall/libraries/provider_firewall_firewalld.rb +0 -179
- data/cookbooks/firewall/libraries/provider_firewall_iptables.rb +0 -171
- data/cookbooks/firewall/libraries/provider_firewall_iptables_ubuntu.rb +0 -200
- data/cookbooks/firewall/libraries/provider_firewall_iptables_ubuntu1404.rb +0 -200
- data/cookbooks/firewall/libraries/provider_firewall_rule.rb +0 -34
- data/cookbooks/firewall/libraries/provider_firewall_ufw.rb +0 -138
- data/cookbooks/firewall/libraries/provider_firewall_windows.rb +0 -126
- data/cookbooks/firewall/libraries/resource_firewall.rb +0 -26
- data/cookbooks/firewall/libraries/resource_firewall_rule.rb +0 -52
- data/cookbooks/firewall/metadata.json +0 -40
- data/cookbooks/firewall/metadata.rb +0 -15
- data/cookbooks/firewall/recipes/default.rb +0 -76
- data/cookbooks/firewall/recipes/firewalld.rb +0 -87
- data/cookbooks/firewall/resources/firewalld.rb +0 -28
- data/cookbooks/firewall/resources/firewalld_config.rb +0 -39
- data/cookbooks/firewall/resources/firewalld_helpers.rb +0 -106
- data/cookbooks/firewall/resources/firewalld_icmptype.rb +0 -88
- data/cookbooks/firewall/resources/firewalld_ipset.rb +0 -104
- data/cookbooks/firewall/resources/firewalld_policy.rb +0 -115
- data/cookbooks/firewall/resources/firewalld_service.rb +0 -98
- data/cookbooks/firewall/resources/firewalld_zone.rb +0 -118
- data/cookbooks/firewall/resources/nftables.rb +0 -71
- data/cookbooks/firewall/resources/nftables_rule.rb +0 -113
- data/cookbooks/firewall/templates/default/ufw/default.erb +0 -13
- /data/cookbooks/{firewall → nagios}/chefignore +0 -0
- /data/cookbooks/{firewall → nagios}/renovate.json +0 -0
@@ -0,0 +1,1710 @@
|
|
1
|
+
# BEGIN COPYRIGHT BLOCK
|
2
|
+
# Copyright (C) 2007 Red Hat, Inc.
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# License: GPL (version 3 or any later version).
|
6
|
+
# See LICENSE for details.
|
7
|
+
# END COPYRIGHT BLOCK
|
8
|
+
#
|
9
|
+
|
10
|
+
package DSUtil;
|
11
|
+
|
12
|
+
use Mozilla::LDAP::Conn;
|
13
|
+
use Mozilla::LDAP::Utils qw(normalizeDN);
|
14
|
+
use Mozilla::LDAP::API qw(:constant ldap_explode_dn ldap_err2string) ; # Direct access to C API
|
15
|
+
use Mozilla::LDAP::LDIF;
|
16
|
+
use File::Spec::Functions qw(rel2abs);
|
17
|
+
use File::Spec;
|
18
|
+
use File::Basename;
|
19
|
+
|
20
|
+
require Exporter;
|
21
|
+
@ISA = qw(Exporter);
|
22
|
+
@EXPORT = qw(portAvailable getAvailablePort isValidDN addSuffix getMappedEntries
|
23
|
+
process_maptbl check_and_add_entry getMappedEntries addErr
|
24
|
+
getHashedPassword debug createInfFromConfig shellEscape
|
25
|
+
isValidServerID isValidUser isValidGroup makePaths getLogin getGroup
|
26
|
+
remove_tree remove_pidfile setDebugLog checkHostname serverIsRunning);
|
27
|
+
@EXPORT_OK = qw(portAvailable getAvailablePort isValidDN addSuffix getMappedEntries
|
28
|
+
process_maptbl check_and_add_entry getMappedEntries addErr
|
29
|
+
getHashedPassword debug createInfFromConfig shellEscape
|
30
|
+
isValidServerID isValidUser isValidGroup makePaths getLogin getGroup
|
31
|
+
remove_tree remove_pidfile setDebugLog checkHostname serverIsRunning);
|
32
|
+
|
33
|
+
use strict;
|
34
|
+
|
35
|
+
my $sockVersion;
|
36
|
+
BEGIN {
|
37
|
+
use Socket;
|
38
|
+
$sockVersion = Socket->VERSION;
|
39
|
+
if ($sockVersion >= 2.000) {
|
40
|
+
import Socket qw ( :addrinfo inet_ntoa
|
41
|
+
unpack_sockaddr_in unpack_sockaddr_in6
|
42
|
+
AF_INET INADDR_ANY
|
43
|
+
PF_INET SO_REUSEADDR SOCK_STREAM SOL_SOCKET );
|
44
|
+
} elsif (eval {require Socket6; 1}) {
|
45
|
+
import Socket6 qw (getaddrinfo getnameinfo unpack_sockaddr_in6);
|
46
|
+
}
|
47
|
+
}
|
48
|
+
$sockVersion = Socket->VERSION;
|
49
|
+
use NetAddr::IP::Util qw( ipv6_n2x );
|
50
|
+
|
51
|
+
use File::Temp qw(tempfile tempdir);
|
52
|
+
use File::Basename qw(dirname);
|
53
|
+
use File::Path qw(rmtree);
|
54
|
+
|
55
|
+
use Carp;
|
56
|
+
|
57
|
+
$DSUtil::debuglevel = 0;
|
58
|
+
$DSUtil::log = 0;
|
59
|
+
|
60
|
+
# use like this:
|
61
|
+
# debug(3, "message");
|
62
|
+
# this will only print "message" if $debuglevel is 3 or higher (-ddd on the command line)
|
63
|
+
sub debug {
|
64
|
+
my ($level, @rest) = @_;
|
65
|
+
if ($level <= $DSUtil::debuglevel) {
|
66
|
+
print STDERR "+" x $level, @rest;
|
67
|
+
if ($DSUtil::log) {
|
68
|
+
$DSUtil::log->logDebug(@rest);
|
69
|
+
}
|
70
|
+
}
|
71
|
+
}
|
72
|
+
|
73
|
+
sub setDebugLog {
|
74
|
+
$DSUtil::log = shift;
|
75
|
+
}
|
76
|
+
|
77
|
+
# return true if the given port number is available, false otherwise
|
78
|
+
sub portAvailable {
|
79
|
+
my $port = shift;
|
80
|
+
my $proto = getprotobyname('tcp');
|
81
|
+
my $rc = socket(SOCK, PF_INET, SOCK_STREAM, $proto);
|
82
|
+
if ($rc == 1) {
|
83
|
+
setsockopt(SOCK, SOL_SOCKET, SO_REUSEADDR, 1);
|
84
|
+
$rc = bind(SOCK, sockaddr_in($port, INADDR_ANY));
|
85
|
+
}
|
86
|
+
close(SOCK);
|
87
|
+
return $rc and ($rc == 1);
|
88
|
+
}
|
89
|
+
|
90
|
+
# returns a randomly assigned port number, or -1
|
91
|
+
# if not able to find an available port
|
92
|
+
sub getAvailablePort {
|
93
|
+
my $MINPORT = 1024;
|
94
|
+
my $MAXPORT = 65535;
|
95
|
+
|
96
|
+
srand( time() ^ ($$ + ($$ << 15)) );
|
97
|
+
while (1) {
|
98
|
+
my $port = $MINPORT + int(rand($MAXPORT-$MINPORT));
|
99
|
+
|
100
|
+
if (portAvailable($port)) {
|
101
|
+
return $port;
|
102
|
+
}
|
103
|
+
}
|
104
|
+
}
|
105
|
+
|
106
|
+
sub isValidDN {
|
107
|
+
my $dn = shift;
|
108
|
+
return ($dn =~ /^[0-9a-zA-Z_-]+=.*$/);
|
109
|
+
}
|
110
|
+
|
111
|
+
sub isValidServerID {
|
112
|
+
my $servid = shift;
|
113
|
+
my $validchars = '#%:\w@_-';
|
114
|
+
if($servid eq "admin"){
|
115
|
+
# "admin" is reserved for the admin server
|
116
|
+
return 0;
|
117
|
+
} else {
|
118
|
+
return $servid =~ /^[$validchars]+$/o;
|
119
|
+
}
|
120
|
+
}
|
121
|
+
|
122
|
+
# we want the name of the effective user id of this process e.g. if someone did
|
123
|
+
# an su root, we want getLogin to return "root" not the originating id (getlogin)
|
124
|
+
# in perl, $> is the effective numeric user id - we need to turn it into a string
|
125
|
+
# use confess here because if we cannot determine the user, something is really,
|
126
|
+
# really wrong and we need to abort immediately
|
127
|
+
sub getLogin {
|
128
|
+
return (getpwuid($>))[0] || $ENV{USER} || confess "Error: could not determine the current user ID: $!";
|
129
|
+
}
|
130
|
+
|
131
|
+
# Look up the primary group name for the supplied user
|
132
|
+
sub getGroup {
|
133
|
+
my $user = shift;
|
134
|
+
my @userinfo = getpwnam($user);
|
135
|
+
|
136
|
+
if(!@userinfo){
|
137
|
+
confess "Error: could not find user ID ($user): $!";
|
138
|
+
}
|
139
|
+
|
140
|
+
return (getgrgid($userinfo[3]))[0] || confess "Error: could not determine the current group name from gid ($userinfo[3]): $!";
|
141
|
+
}
|
142
|
+
|
143
|
+
sub isValidUser {
|
144
|
+
my $user = shift;
|
145
|
+
# convert numeric uid to string
|
146
|
+
my $strans = $user;
|
147
|
+
if ($user =~ /^\d+$/) { # numeric - convert to string
|
148
|
+
$strans = getpwuid $user;
|
149
|
+
if (!$strans) {
|
150
|
+
return ("dialog_ssuser_error", $user);
|
151
|
+
}
|
152
|
+
}
|
153
|
+
if ($> != 0) { # if not root, the user must be our uid
|
154
|
+
my $username = getLogin;
|
155
|
+
if ($strans ne $username) {
|
156
|
+
return ("dialog_ssuser_must_be_same", $username);
|
157
|
+
}
|
158
|
+
} else { # user is root - verify id
|
159
|
+
my $nuid = getpwnam $strans;
|
160
|
+
if (!defined($nuid)) {
|
161
|
+
return ("dialog_ssuser_error", $user);
|
162
|
+
}
|
163
|
+
if (!$nuid) {
|
164
|
+
debug(0, "Warning: using root as the server user id. You are strongly encouraged to use a non-root user.\n");
|
165
|
+
}
|
166
|
+
}
|
167
|
+
|
168
|
+
return ();
|
169
|
+
}
|
170
|
+
|
171
|
+
sub isValidGroup {
|
172
|
+
my $group = shift;
|
173
|
+
my $ngid;
|
174
|
+
# convert numeric gid to string
|
175
|
+
my $strans = $group;
|
176
|
+
if ($group =~ /^\d+$/) { # numeric - convert to string
|
177
|
+
$strans = (getgrgid($group))[0];
|
178
|
+
if (!$strans) {
|
179
|
+
return ("dialog_ssgroup_error", $group);
|
180
|
+
}
|
181
|
+
}
|
182
|
+
# ensure the specified group is a defined group
|
183
|
+
$ngid = getgrnam $strans;
|
184
|
+
if (!defined($ngid)) {
|
185
|
+
return ("dialog_ssgroup_error", $group);
|
186
|
+
}
|
187
|
+
|
188
|
+
return ();
|
189
|
+
}
|
190
|
+
|
191
|
+
# arguments
|
192
|
+
# - hostname - the hostname to look for
|
193
|
+
# - res - the Resource object to use to construct messages
|
194
|
+
# returns - the error message string, or "" upon success if $res exists
|
195
|
+
# - the error message array, or () upon success otherwise
|
196
|
+
sub checkHostname {
|
197
|
+
my $hn = shift;
|
198
|
+
my $res = shift;
|
199
|
+
|
200
|
+
# see if hostname is an fqdn
|
201
|
+
if ($hn !~ /\./) {
|
202
|
+
if ($res) {
|
203
|
+
return $res->getText('warning_hostname_not_fully_qualified', $hn);
|
204
|
+
} else {
|
205
|
+
return ('warning_hostname_not_fully_qualified', $hn);
|
206
|
+
}
|
207
|
+
}
|
208
|
+
|
209
|
+
# see if we can resolve the hostname (IPv6 supported)
|
210
|
+
my $found = 0;
|
211
|
+
my @hostip = ();
|
212
|
+
if ($sockVersion >= 2.000) {
|
213
|
+
debug(1, "Socket version $sockVersion\n");
|
214
|
+
my %hints = (socktype => SOCK_STREAM);
|
215
|
+
my ($err, @aires) = getaddrinfo($hn, "ldap", \%hints);
|
216
|
+
if ($err) {
|
217
|
+
if ($res) {
|
218
|
+
return $res->getText('warning_no_such_hostname', $hn);
|
219
|
+
} else {
|
220
|
+
return ('warning_no_such_hostname', $hn);
|
221
|
+
}
|
222
|
+
}
|
223
|
+
while (my $ai = shift @aires) {
|
224
|
+
debug(1, "found for hostname $hn\n");
|
225
|
+
my $ip;
|
226
|
+
if ($ai->{family} == AF_INET) {
|
227
|
+
my ( $port, $ipaddr ) = unpack_sockaddr_in( $ai->{addr} );
|
228
|
+
$ip = inet_ntoa($ipaddr);
|
229
|
+
} else {
|
230
|
+
my ( $port, $ipaddr ) = unpack_sockaddr_in6( $ai->{addr} );
|
231
|
+
$ip = ipv6_n2x($ipaddr);
|
232
|
+
}
|
233
|
+
debug(1, "ipaddr=", $ip, "\n");
|
234
|
+
# see if reverse resolution works
|
235
|
+
my ($err, $hn2, $service) = getnameinfo($ai->{addr});
|
236
|
+
if (!$err) {
|
237
|
+
push @hostip, [$hn2, $ip];
|
238
|
+
if (lc($hn) eq lc($hn2)) {
|
239
|
+
$found = 1;
|
240
|
+
last;
|
241
|
+
}
|
242
|
+
}
|
243
|
+
}
|
244
|
+
if (!$found) {
|
245
|
+
system("/usr/bin/host -t CNAME $hn 2>&1 1> /dev/null");
|
246
|
+
if ($? == 0){
|
247
|
+
$found = 1;
|
248
|
+
}
|
249
|
+
}
|
250
|
+
} elsif (eval {require Socket6; 1}) {
|
251
|
+
debug(1, "Socket6\n");
|
252
|
+
my @aires = getaddrinfo($hn, "ldap", AF_UNSPEC, SOCK_STREAM);
|
253
|
+
if (scalar(@aires) < 5) {
|
254
|
+
if ($res) {
|
255
|
+
return $res->getText('warning_no_such_hostname', $hn);
|
256
|
+
} else {
|
257
|
+
return ('warning_no_such_hostname', $hn);
|
258
|
+
}
|
259
|
+
}
|
260
|
+
my $ailen = scalar(@aires);
|
261
|
+
while ($ailen >= 5) {
|
262
|
+
debug(1, "found for hostname $hn\n");
|
263
|
+
my $family = shift @aires;
|
264
|
+
my $socktype = shift @aires;
|
265
|
+
my $proto = shift @aires;
|
266
|
+
my $saddr = shift @aires;
|
267
|
+
my $canonname = shift @aires;
|
268
|
+
$ailen = scalar(@aires);
|
269
|
+
my $ip;
|
270
|
+
if ($family == AF_INET) {
|
271
|
+
my ($port, $ipaddr) = unpack_sockaddr_in($saddr);
|
272
|
+
$ip = inet_ntoa($ipaddr);
|
273
|
+
} else {
|
274
|
+
my ($port, $ipaddr) = unpack_sockaddr_in6($saddr);
|
275
|
+
$ip = ipv6_n2x($ipaddr);
|
276
|
+
}
|
277
|
+
debug(1, "ipaddr=", $ip, "\n");
|
278
|
+
# see if reverse resolution works
|
279
|
+
my ($hn2, $service) = getnameinfo($saddr);
|
280
|
+
if ($hn2) {
|
281
|
+
push @hostip, [$hn2, $ip];
|
282
|
+
if (lc($hn) eq lc($hn2)) {
|
283
|
+
$found = 1;
|
284
|
+
}
|
285
|
+
}
|
286
|
+
}
|
287
|
+
} else {
|
288
|
+
debug(1, "gethostbyname ...\n");
|
289
|
+
# see if we can resolve the hostname
|
290
|
+
my ($name, $aliases, $addrtype, $length, @addrs) = gethostbyname($hn);
|
291
|
+
if (!$name) {
|
292
|
+
if ($res) {
|
293
|
+
return $res->getText('warning_no_such_hostname', $hn);
|
294
|
+
} else {
|
295
|
+
return ('warning_no_such_hostname', $hn);
|
296
|
+
}
|
297
|
+
}
|
298
|
+
debug(1, "found for hostname $hn: name=$name\n");
|
299
|
+
debug(1, "aliases=$aliases\n");
|
300
|
+
debug(1, "addrtype=$addrtype\n");
|
301
|
+
# see if reverse resolution works
|
302
|
+
foreach my $ii (@addrs) {
|
303
|
+
my $hn2 = gethostbyaddr($ii, $addrtype);
|
304
|
+
my $ip = join('.', unpack('C4', $ii));
|
305
|
+
debug(1, "\thost=$hn2 ip=$ip\n");
|
306
|
+
push @hostip, [$hn2, $ip];
|
307
|
+
if (lc($hn) eq lc($hn2)) {
|
308
|
+
$found = 1;
|
309
|
+
last;
|
310
|
+
}
|
311
|
+
}
|
312
|
+
}
|
313
|
+
|
314
|
+
if (!$found) {
|
315
|
+
if ($res) {
|
316
|
+
my $retstr = "";
|
317
|
+
$retstr = $res->getText('warning_reverse_resolve', $hn, $hn);
|
318
|
+
for my $ii (@hostip) {
|
319
|
+
$retstr .= $res->getText('warning_reverse_resolve_sub', $ii->[1], $ii->[0]);
|
320
|
+
}
|
321
|
+
return $retstr;
|
322
|
+
} else {
|
323
|
+
my @reterrs = ();
|
324
|
+
push @reterrs, [ 'warning_reverse_resolve', $hn, $hn ];
|
325
|
+
for my $ii (@hostip) {
|
326
|
+
push @reterrs, [ 'warning_reverse_resolve_sub', $ii->[1], $ii->[0] ];
|
327
|
+
}
|
328
|
+
return @reterrs;
|
329
|
+
}
|
330
|
+
}
|
331
|
+
|
332
|
+
debug(1, "hostname $hn resolves correctly\n");
|
333
|
+
if ($res) {
|
334
|
+
return '';
|
335
|
+
} else {
|
336
|
+
return ();
|
337
|
+
}
|
338
|
+
}
|
339
|
+
|
340
|
+
# delete the subtree starting from the passed entry
|
341
|
+
sub delete_all
|
342
|
+
{
|
343
|
+
my ($conn, $bentry) = @_;
|
344
|
+
my $sentry = $conn->search($bentry->{dn},
|
345
|
+
"subtree", "(objectclass=*)", 0, ("dn"));
|
346
|
+
my @mystack = ();
|
347
|
+
while ($sentry) {
|
348
|
+
push @mystack, $sentry->getDN();
|
349
|
+
$sentry = $conn->nextEntry();
|
350
|
+
}
|
351
|
+
# reverse order
|
352
|
+
my $dn = pop @mystack;
|
353
|
+
while ($dn) {
|
354
|
+
$conn->delete($dn);
|
355
|
+
my $rc = $conn->getErrorCode();
|
356
|
+
if ( $rc != 0 ) {
|
357
|
+
debug(1, "ERROR: unable to delete entry $dn, error code: $rc:" . $conn->getErrorString() . "\n");
|
358
|
+
return 1;
|
359
|
+
}
|
360
|
+
$dn = pop @mystack;
|
361
|
+
}
|
362
|
+
return 0;
|
363
|
+
}
|
364
|
+
|
365
|
+
# if the entry does not exist on the server, add the entry.
|
366
|
+
# otherwise, do nothing
|
367
|
+
# you can use this as the callback to getMappedEntries, so
|
368
|
+
# that for each entry in the ldif file being processed, you
|
369
|
+
# can call this subroutine to add or update the entry
|
370
|
+
# use like this:
|
371
|
+
# getMappedEntries($mapper, \@ldiffiles, \&check_and_add_entry,
|
372
|
+
# [$conn, $fresh, $verbose]);
|
373
|
+
# where $conn is a perldap Conn
|
374
|
+
# $fresh if true will update the entry if it exists
|
375
|
+
# $verbose prints out more info
|
376
|
+
sub check_and_add_entry
|
377
|
+
{
|
378
|
+
my ($context, $aentry, $errs) = @_;
|
379
|
+
my $conn = $context->[0];
|
380
|
+
my $fresh = $context->[1];
|
381
|
+
my $verbose = $context->[2];
|
382
|
+
my @ctypes = $aentry->getValues("changetype");
|
383
|
+
my $sentry = $conn->search($aentry->{dn}, "base", "(objectclass=*)", 0, ("*", "aci"));
|
384
|
+
if ($sentry) {
|
385
|
+
debug(3, "check_and_add_entry: Found entry " . $sentry->getDN() . "\n");
|
386
|
+
if ( (! @ctypes) or ("add" eq lc($ctypes[0])) ) { # entry exists, and this is not a modify op
|
387
|
+
# or add is explicitely specified
|
388
|
+
debug(3, "check_and_add_entry: skipping entry " . $sentry->getDN() . "\n");
|
389
|
+
return 1; # ignore - return success
|
390
|
+
}
|
391
|
+
} else {
|
392
|
+
debug(3, "check_and_add_entry: Entry not found " . $aentry->{dn} .
|
393
|
+
" error " . $conn->getErrorString() . "\n");
|
394
|
+
if (@ctypes and !("add" eq lc($ctypes[0]))) { # uh oh - attempt to del/mod an entry that doesn't exist
|
395
|
+
debug(3, "check_and_add_entry: attepting to @ctypes the entry " . $aentry->{dn} .
|
396
|
+
" that does not exist\n");
|
397
|
+
return 1; # ignore - return success
|
398
|
+
}
|
399
|
+
}
|
400
|
+
do
|
401
|
+
{
|
402
|
+
my @addtypes; # list of attr types for mod add
|
403
|
+
my @reptypes; # list of attr types for mod replace
|
404
|
+
my @deltypes; # list of attr types for mod delete
|
405
|
+
my $OP_NONE = 0;
|
406
|
+
my $OP_ADD = 1;
|
407
|
+
my $OP_MOD = 2;
|
408
|
+
my $OP_DEL = 3;
|
409
|
+
# $op stores either of the above $OP_ values
|
410
|
+
my $op = $OP_NONE;
|
411
|
+
if ( (0 > $#ctypes) or ("add" eq lc($ctypes[0])) ) # aentry: complete entry
|
412
|
+
{
|
413
|
+
$op = $OP_ADD; # just add the entry
|
414
|
+
}
|
415
|
+
else # aentry: modify format
|
416
|
+
{
|
417
|
+
if ( $sentry )
|
418
|
+
{
|
419
|
+
if ( "delete" eq lc($ctypes[0]) )
|
420
|
+
{
|
421
|
+
$op = $OP_DEL;
|
422
|
+
}
|
423
|
+
else
|
424
|
+
{
|
425
|
+
@addtypes = $aentry->getValues("add");
|
426
|
+
@reptypes = $aentry->getValues("replace");
|
427
|
+
@deltypes = $aentry->getValues("delete");
|
428
|
+
$op = $OP_MOD;
|
429
|
+
}
|
430
|
+
}
|
431
|
+
else
|
432
|
+
{
|
433
|
+
$op = $OP_NONE;
|
434
|
+
}
|
435
|
+
}
|
436
|
+
|
437
|
+
if ( $OP_ADD == $op )
|
438
|
+
{
|
439
|
+
if ("add" eq lc($ctypes[0])) {
|
440
|
+
# remove the changetype: add from the entry
|
441
|
+
$aentry->remove('changetype');
|
442
|
+
}
|
443
|
+
$conn->add($aentry);
|
444
|
+
my $rc = $conn->getErrorCode();
|
445
|
+
if ( $rc != 0 )
|
446
|
+
{
|
447
|
+
my $string = $conn->getErrorString();
|
448
|
+
push @{$errs}, 'error_adding_entry', $aentry->{dn}, $string;
|
449
|
+
debug(1, "ERROR: adding an entry $aentry->{dn} failed, error: $string\n");
|
450
|
+
$aentry->printLDIF();
|
451
|
+
$conn->close();
|
452
|
+
return 0;
|
453
|
+
}
|
454
|
+
debug(1, "Entry $aentry->{dn} is added\n");
|
455
|
+
}
|
456
|
+
elsif ( $OP_DEL == $op )
|
457
|
+
{
|
458
|
+
my $rc = delete_all($conn, $sentry);
|
459
|
+
if ( 0 != $rc )
|
460
|
+
{
|
461
|
+
push @{$errs}, 'error_deleteall_entries', $sentry->{dn}, $conn->getErrorString();
|
462
|
+
debug(1, "Error deleting $sentry->{dn}\n");
|
463
|
+
return 0;
|
464
|
+
}
|
465
|
+
debug(1, "Entry $aentry->{dn} is deleted\n");
|
466
|
+
$sentry = undef;
|
467
|
+
}
|
468
|
+
elsif ( 0 < $op ) # modify op
|
469
|
+
{
|
470
|
+
my $attr;
|
471
|
+
my @errsToIgnore;
|
472
|
+
if (@addtypes) {
|
473
|
+
push @errsToIgnore, LDAP_TYPE_OR_VALUE_EXISTS;
|
474
|
+
}
|
475
|
+
foreach $attr ( @addtypes )
|
476
|
+
{
|
477
|
+
foreach my $val ($aentry->getValues($attr))
|
478
|
+
{
|
479
|
+
debug(3, "Adding attr=$attr value=$val to entry $aentry->{dn}\n");
|
480
|
+
$sentry->addValue( $attr, $val );
|
481
|
+
}
|
482
|
+
}
|
483
|
+
foreach $attr ( @reptypes )
|
484
|
+
{
|
485
|
+
my @vals = $aentry->getValues($attr);
|
486
|
+
debug(3, "Replacing attr=$attr values=" . $aentry->getValues($attr) . " to entry $aentry->{dn}\n");
|
487
|
+
$sentry->setValues($attr, @vals);
|
488
|
+
}
|
489
|
+
if (@deltypes) {
|
490
|
+
push @errsToIgnore, LDAP_NO_SUCH_ATTRIBUTE;
|
491
|
+
}
|
492
|
+
foreach $attr ( @deltypes )
|
493
|
+
{
|
494
|
+
# removeValue takes a single value only
|
495
|
+
if (!$aentry->size($attr))
|
496
|
+
{
|
497
|
+
debug(3, "Deleting attr=$attr from entry $aentry->{dn}\n");
|
498
|
+
$sentry->remove($attr); # just delete the attribute
|
499
|
+
}
|
500
|
+
else
|
501
|
+
{
|
502
|
+
debug(3, "Deleting attr=$attr values=" . $aentry->getValues($attr) . " from entry $aentry->{dn}\n");
|
503
|
+
foreach my $val ($aentry->getValues($attr))
|
504
|
+
{
|
505
|
+
$sentry->removeValue($attr, $val);
|
506
|
+
}
|
507
|
+
}
|
508
|
+
}
|
509
|
+
$conn->update($sentry);
|
510
|
+
my $rc = $conn->getErrorCode();
|
511
|
+
if ( $rc != 0 )
|
512
|
+
{
|
513
|
+
my $string = $conn->getErrorString();
|
514
|
+
debug(1, "ERROR: updating an entry $sentry->{dn} failed, error: $string\n");
|
515
|
+
if (grep /^$rc$/, @errsToIgnore) {
|
516
|
+
debug(1, "Ignoring error $rc returned by adding @addtypes deleting @deltypes\n");
|
517
|
+
} else {
|
518
|
+
push @{$errs}, 'error_updating_entry', $sentry->{dn}, $string;
|
519
|
+
$aentry->printLDIF();
|
520
|
+
$conn->close();
|
521
|
+
return 0;
|
522
|
+
}
|
523
|
+
}
|
524
|
+
}
|
525
|
+
if ( $sentry )
|
526
|
+
{
|
527
|
+
$sentry = $conn->nextEntry(); # supposed to have no more entries
|
528
|
+
}
|
529
|
+
} until ( !$sentry );
|
530
|
+
out:
|
531
|
+
return 1;
|
532
|
+
}
|
533
|
+
|
534
|
+
# the default callback used with getMappedEntries
|
535
|
+
# just adds the given entry to the given list
|
536
|
+
sub cbaddent {
|
537
|
+
my $list = shift;
|
538
|
+
my $ent = shift;
|
539
|
+
push @{$list}, $ent;
|
540
|
+
return 1;
|
541
|
+
}
|
542
|
+
|
543
|
+
# given a mapper and a list of LDIF files, produce a list of
|
544
|
+
# perldap Entry objects which have had their tokens subst-ed
|
545
|
+
# with values from the mapper
|
546
|
+
# An optional callback can be supplied. Each entry will be
|
547
|
+
# given to this callback. The callback should return a list
|
548
|
+
# of localizable errors. If no callback is supplied, the
|
549
|
+
# entries will be returned in a list.
|
550
|
+
# Arguments:
|
551
|
+
# mapper - a hash ref - the keys are the tokens to replace
|
552
|
+
# and the values are the replacements
|
553
|
+
# ldiffiles - an array ref - the list of LDIF files to
|
554
|
+
# operate on
|
555
|
+
# errs - an array ref - this is filled in with the
|
556
|
+
# errors encountered in processing - this is
|
557
|
+
# suitable for passing to setup->msg or
|
558
|
+
# Resource->getText
|
559
|
+
# callback (optional) - a code ref - a ref to a subroutine
|
560
|
+
# that will be called with each entry - see below
|
561
|
+
# context (optional) - this will be passed as the first
|
562
|
+
# argument to your given callback - see below
|
563
|
+
# Callback:
|
564
|
+
# The callback sub will be called for each entry after
|
565
|
+
# the entry has been converted. The callback will be
|
566
|
+
# called with the given context as the first argument
|
567
|
+
# and the Mozilla::LDAP::Entry as the second argument,
|
568
|
+
# and an errs array ref as the third argument. The
|
569
|
+
# callback should return true to continue processing,
|
570
|
+
# or false if a fatal error was encountered that should
|
571
|
+
# abort processing of any further.
|
572
|
+
# Errors:
|
573
|
+
# This function should return an array of errors in the
|
574
|
+
# format described below, for use with Resource::getText()
|
575
|
+
# or Setup::msg()
|
576
|
+
# Return:
|
577
|
+
# The return value is a list of entries.
|
578
|
+
# Example usage:
|
579
|
+
# sub handle_entries {
|
580
|
+
# my $context = shift;
|
581
|
+
# my $entry = shift;
|
582
|
+
# my $errs = shift;
|
583
|
+
# .... do something with entry ....
|
584
|
+
# .... if $context is Mozilla::LDAP::Conn, $conn->add($entry); ...
|
585
|
+
# .... report errors ....
|
586
|
+
# if ($fatalerror) {
|
587
|
+
# push @{$errs}, 'error_token', arg1, arg2, ...;
|
588
|
+
# return 0;
|
589
|
+
# } else {
|
590
|
+
# return 1;
|
591
|
+
# }
|
592
|
+
# }
|
593
|
+
# $mapper = {foo => 'bar', baz => 'biff'};
|
594
|
+
# @ldiffiles = ('foo.ldif', 'bar.ldif', ..., 'biff.ldif');
|
595
|
+
# $conn = new Mozilla::LDAP::Conn(...);
|
596
|
+
# my @errs;
|
597
|
+
# @entries = getMappedEntries($mapper, \@ldiffiles, \@errs, \&handle_entries, $conn);
|
598
|
+
# Note that this will return 0 entries since a callback was used.
|
599
|
+
# The simpler example is this:
|
600
|
+
# @entries = getMappedEntries($mapper, \@ldiffiles, \@errs);
|
601
|
+
#
|
602
|
+
sub getMappedEntries {
|
603
|
+
my $mapper = shift;
|
604
|
+
my $ldiffiles = shift;
|
605
|
+
my $errs = shift;
|
606
|
+
my $callback = shift || \&cbaddent; # default - just add entry to @entries
|
607
|
+
my @entries = ();
|
608
|
+
my $context = shift || \@entries;
|
609
|
+
my $error;
|
610
|
+
|
611
|
+
if (!ref($ldiffiles)) {
|
612
|
+
$ldiffiles = [ $ldiffiles ];
|
613
|
+
}
|
614
|
+
|
615
|
+
foreach my $ldiffile (@{$ldiffiles}) {
|
616
|
+
if (!open(MYLDIF, "< $ldiffile")) {
|
617
|
+
push @{$errs}, "error_opening_ldiftmpl", $ldiffile, $!;
|
618
|
+
return 0;
|
619
|
+
}
|
620
|
+
my $in = new Mozilla::LDAP::LDIF(*MYLDIF);
|
621
|
+
debug(1, "Processing $ldiffile ...\n");
|
622
|
+
ENTRY: while (my $entry = Mozilla::LDAP::LDIF::readOneEntry($in)) {
|
623
|
+
# first, fix the DN
|
624
|
+
my $dn = $entry->getDN();
|
625
|
+
my $origdn = $dn;
|
626
|
+
while ( $dn =~ /%([\w_-]+)%/ ) {
|
627
|
+
if (exists($mapper->{$1})) {
|
628
|
+
$dn =~ s{%([\w_-]+)%}{$mapper->{$1}}ge;
|
629
|
+
} else {
|
630
|
+
push @{$errs}, 'error_mapping_token_ldiftmpl', $dn, $ldiffile, $1;
|
631
|
+
$error = 1;
|
632
|
+
last ENTRY;
|
633
|
+
}
|
634
|
+
}
|
635
|
+
$entry->setDN($dn);
|
636
|
+
# next, fix all of the values in all of the attributes
|
637
|
+
foreach my $attr (keys %{$entry}) {
|
638
|
+
my @newvalues = ();
|
639
|
+
foreach my $value ($entry->getValues($attr)) {
|
640
|
+
# Need to repeat to handle nested subst
|
641
|
+
my $origvalue = $value;
|
642
|
+
while ( $value =~ /%([\w_-]+)%/ ) {
|
643
|
+
if (exists($mapper->{$1})) {
|
644
|
+
$value =~ s{%([\w_-]+)%}{$mapper->{$1}}ge;
|
645
|
+
} else {
|
646
|
+
push @{$errs}, 'error_mapping_token_ldiftmpl', $dn, $ldiffile, $1;
|
647
|
+
debug(1, "ERROR: \"$origvalue\" mapped to \"$value\".\n");
|
648
|
+
$error = 1;
|
649
|
+
last ENTRY;
|
650
|
+
}
|
651
|
+
}
|
652
|
+
push @newvalues, $value;
|
653
|
+
}
|
654
|
+
$entry->setValues( $attr, @newvalues );
|
655
|
+
}
|
656
|
+
|
657
|
+
if (!&{$callback}($context, $entry, $errs)) {
|
658
|
+
debug(1, "ERROR: There was an error processing entry ". $entry->getDN(). "\n");
|
659
|
+
debug(1, "Cannot continue processing entries.\n");
|
660
|
+
$error = 1;
|
661
|
+
last ENTRY;
|
662
|
+
}
|
663
|
+
|
664
|
+
}
|
665
|
+
close(MYLDIF);
|
666
|
+
last if ($error); # do not process any more ldiffiles if an error occurred
|
667
|
+
}
|
668
|
+
|
669
|
+
return @entries;
|
670
|
+
}
|
671
|
+
|
672
|
+
# you should only use this function if you know for sure
|
673
|
+
# that the suffix and backend do not already exist
|
674
|
+
# use addSuffix instead
|
675
|
+
sub newSuffixAndBackend {
|
676
|
+
my $context = shift;
|
677
|
+
my $suffix = shift;
|
678
|
+
my $bename = shift;
|
679
|
+
my $nsuffix = normalizeDN($suffix);
|
680
|
+
my @errs;
|
681
|
+
|
682
|
+
my $dn = "cn=$bename, cn=ldbm database, cn=plugins, cn=config";
|
683
|
+
my $entry = new Mozilla::LDAP::Entry();
|
684
|
+
$entry->setDN($dn);
|
685
|
+
$entry->setValues('objectclass', 'top', 'extensibleObject', 'nsBackendInstance');
|
686
|
+
$entry->setValues('cn', $bename);
|
687
|
+
$entry->setValues('nsslapd-suffix', $nsuffix);
|
688
|
+
$context->add($entry);
|
689
|
+
my $rc = $context->getErrorCode();
|
690
|
+
if ($rc) {
|
691
|
+
return ('error_creating_suffix_backend', $suffix, $bename, $context->getErrorString());
|
692
|
+
}
|
693
|
+
|
694
|
+
$entry = new Mozilla::LDAP::Entry();
|
695
|
+
$dn = "cn=\"$nsuffix\", cn=mapping tree, cn=config";
|
696
|
+
$entry->setDN($dn);
|
697
|
+
$entry->setValues('objectclass', 'top', 'extensibleObject', 'nsMappingTree');
|
698
|
+
$entry->setValues('cn', "\"$nsuffix\"");
|
699
|
+
$entry->setValues('nsslapd-state', 'backend');
|
700
|
+
$entry->setValues('nsslapd-backend', $bename);
|
701
|
+
$context->add($entry);
|
702
|
+
$rc = $context->getErrorCode();
|
703
|
+
if ($rc) {
|
704
|
+
return ('error_creating_suffix', $suffix, $context->getErrorString());
|
705
|
+
}
|
706
|
+
|
707
|
+
return ();
|
708
|
+
}
|
709
|
+
|
710
|
+
sub findbecb {
|
711
|
+
my $entry = shift;
|
712
|
+
my $attrs = shift;
|
713
|
+
return $entry->hasValue('objectclass', $attrs->[0], 1) &&
|
714
|
+
$entry->hasValue('cn', $attrs->[1], 1);
|
715
|
+
}
|
716
|
+
|
717
|
+
sub findBackend {
|
718
|
+
my $context = shift;
|
719
|
+
my $bename = shift;
|
720
|
+
my $ent;
|
721
|
+
if (ref($context) eq 'Mozilla::LDAP::Conn') {
|
722
|
+
$ent = $context->search("cn=ldbm database,cn=plugins,cn=config", "one",
|
723
|
+
"(&(objectclass=nsBackendInstance)(cn=$bename)")
|
724
|
+
} else {
|
725
|
+
$ent = $context->search("cn=ldbm database,cn=plugins,cn=config", "one",
|
726
|
+
\&findbecb, ['nsBackendInstance', $bename])
|
727
|
+
}
|
728
|
+
}
|
729
|
+
|
730
|
+
sub findsuffixcb {
|
731
|
+
my $entry = shift;
|
732
|
+
my $attrs = shift;
|
733
|
+
return $entry->hasValue('cn', $attrs->[0], 1) ||
|
734
|
+
$entry->hasValue('cn', $attrs->[1], 1);
|
735
|
+
}
|
736
|
+
|
737
|
+
sub findSuffix {
|
738
|
+
my $context = shift;
|
739
|
+
my $suffix = shift;
|
740
|
+
my $nsuffix = normalizeDN($suffix);
|
741
|
+
my $ent;
|
742
|
+
if (ref($context) eq 'Mozilla::LDAP::Conn') {
|
743
|
+
$ent = $context->search("cn=mapping tree,cn=config", "one",
|
744
|
+
"(|(cn=\"$suffix\")(cn=\"$nsuffix\"))");
|
745
|
+
} else {
|
746
|
+
$ent = $context->search("cn=mapping tree,cn=config", "one",
|
747
|
+
\&findsuffixcb, ["\"$suffix\"", "\"$nsuffix\""])
|
748
|
+
}
|
749
|
+
}
|
750
|
+
|
751
|
+
sub getUniqueBackendName {
|
752
|
+
my $context = shift;
|
753
|
+
my $bename = "backend";
|
754
|
+
my $index = 0;
|
755
|
+
my $ent = findBackend($context, ($bename . $index));
|
756
|
+
while ($ent) {
|
757
|
+
++$index;
|
758
|
+
$ent = findBackend($context, ($bename . $index));
|
759
|
+
}
|
760
|
+
|
761
|
+
return $bename.$index;
|
762
|
+
}
|
763
|
+
|
764
|
+
sub addSuffix {
|
765
|
+
my $context = shift; # Conn
|
766
|
+
my $suffix = shift;
|
767
|
+
my $bename = shift; # optional
|
768
|
+
my $ent;
|
769
|
+
|
770
|
+
if ($bename && ($ent = findBackend($context, $bename))) {
|
771
|
+
return ('backend_already_exists', $bename, $ent->getDN());
|
772
|
+
}
|
773
|
+
|
774
|
+
if ($ent = findSuffix($context, $suffix)) {
|
775
|
+
return ('suffix_already_exists', $suffix, $ent->getDN());
|
776
|
+
}
|
777
|
+
|
778
|
+
if (!$bename) {
|
779
|
+
$bename = getUniqueBackendName($context);
|
780
|
+
}
|
781
|
+
|
782
|
+
my @errs = newSuffixAndBackend($context, $suffix, $bename);
|
783
|
+
|
784
|
+
return @errs;
|
785
|
+
}
|
786
|
+
|
787
|
+
# process map table
|
788
|
+
# [map table sample]
|
789
|
+
# fqdn = FullMachineName
|
790
|
+
# hostname = `use Sys::Hostname; $returnvalue = hostname();`
|
791
|
+
# ds_console_jar ="%normbrand%-ds-%ds_version%.jar"
|
792
|
+
#
|
793
|
+
# * If the right-hand value is in ` (backquote), the value is eval'ed by perl.
|
794
|
+
# The output should be stored in $returnvalue to pass to the internal hash.
|
795
|
+
# * If the right-hand value is in " (doublequote), the value is passed as is.
|
796
|
+
# * If the right-hand value is not in any quote, the value should be found
|
797
|
+
# in either of the setup inf file (static) or the install inf file (dynamic).
|
798
|
+
# * Variables surrounded by @ (e.g., @admin_confdir@) are replaced with the
|
799
|
+
# system path at the compile time.
|
800
|
+
# * The right-hand value can contain variables surrounded by % (e.g., %asid%)
|
801
|
+
# which refers the right-hand value (key) of this map file.
|
802
|
+
# The %token% tokens are replaced in getMappedEntries
|
803
|
+
sub process_maptbl
|
804
|
+
{
|
805
|
+
my ($mapper, $errs, @infdata) = @_;
|
806
|
+
my @deferredkeys = ();
|
807
|
+
|
808
|
+
if (defined($mapper->{""})) {
|
809
|
+
$mapper = $mapper->{""}; # side effect of Inf with no sections
|
810
|
+
}
|
811
|
+
|
812
|
+
KEY: foreach my $key (keys %{$mapper})
|
813
|
+
{
|
814
|
+
my $value = $mapper->{$key};
|
815
|
+
if ($value =~ /^\"/)
|
816
|
+
{
|
817
|
+
$value =~ tr/\"//d; # value is a regular double quoted string - remove quotes
|
818
|
+
$mapper->{$key} = $value;
|
819
|
+
}
|
820
|
+
elsif ($value =~ /^\`/)
|
821
|
+
{
|
822
|
+
push @deferredkeys, $key; # process these last
|
823
|
+
}
|
824
|
+
else
|
825
|
+
{
|
826
|
+
# get the value from one of the Inf passed in
|
827
|
+
# they $value could be pure Key or Key:"default_value"
|
828
|
+
my ($key_value, $default_value) = split(/:/, $value, 2);
|
829
|
+
my $infsection;
|
830
|
+
foreach my $thisinf (@infdata)
|
831
|
+
{
|
832
|
+
foreach my $section0 (keys %{$thisinf})
|
833
|
+
{
|
834
|
+
$infsection = $thisinf->{$section0};
|
835
|
+
next if (!ref($infsection));
|
836
|
+
if (defined($infsection->{$key_value}))
|
837
|
+
{
|
838
|
+
$mapper->{$key} = $infsection->{$key_value};
|
839
|
+
next KEY;
|
840
|
+
}
|
841
|
+
}
|
842
|
+
}
|
843
|
+
if ($default_value ne "")
|
844
|
+
{
|
845
|
+
$default_value =~ tr/\"//d; # default_value is a regular double quoted string - remove quotes
|
846
|
+
$mapper->{$key} = $default_value;
|
847
|
+
}
|
848
|
+
else
|
849
|
+
{
|
850
|
+
push @{$errs}, ['no_mapvalue_for_key', $value, $key];
|
851
|
+
return {};
|
852
|
+
}
|
853
|
+
}
|
854
|
+
}
|
855
|
+
|
856
|
+
# we have to process the perl expressions to eval last, because those
|
857
|
+
# expressions may use mappings defined elsewhere in the file, and we are not
|
858
|
+
# guaranteed of the order in which hash keys are enumerated
|
859
|
+
foreach my $key (@deferredkeys) {
|
860
|
+
my $value = $mapper->{$key};
|
861
|
+
$value =~ tr/\`//d; # value is a perl expression to eval
|
862
|
+
my $returnvalue; # set in eval expression
|
863
|
+
eval $value;
|
864
|
+
$mapper->{$key} = $returnvalue; # perl expression sets $returnvalue
|
865
|
+
}
|
866
|
+
|
867
|
+
return $mapper;
|
868
|
+
}
|
869
|
+
|
870
|
+
# given a string, escape the characters in the string
|
871
|
+
# so that it can be safely passed to the shell via
|
872
|
+
# the system() call or `` backticks
|
873
|
+
sub shellEscape {
|
874
|
+
my $val = shift;
|
875
|
+
# first, escape the double quotes and slashes
|
876
|
+
$val =~ s/([\\"])/\\$1/g; # " font lock fun
|
877
|
+
# next, escape the rest of the special chars
|
878
|
+
my $special = '!$\' @#%^&*()|[\]{};:<>?/`';
|
879
|
+
$val =~ s/([$special])/\\$1/g;
|
880
|
+
|
881
|
+
return $val;
|
882
|
+
}
|
883
|
+
|
884
|
+
# given a string, escape the special characters in the string.
|
885
|
+
# the characters are defined in RFC 4514.
|
886
|
+
# special = escaped / SPACE / SHARP / EQUALS
|
887
|
+
# escaped = DQUOTE / PLUS / COMMA / SEMI / LANGLE / RANGLE
|
888
|
+
# hex string "# HEX HEX" is unlikely appearing in the installation.
|
889
|
+
# thus, it won't be supported for now.
|
890
|
+
my %dnspecial = (
|
891
|
+
'"' => '\\"', # '\\22'
|
892
|
+
'\+' => '\\+', # '\\2B'
|
893
|
+
',' => '\\,', # '\\2C'
|
894
|
+
';' => '\\;', # '\\3B'
|
895
|
+
'<' => '\\<', # '\\3C'
|
896
|
+
'>' => '\\>', # '\\3E'
|
897
|
+
'=' => '\\=' # '\\3D'
|
898
|
+
);
|
899
|
+
|
900
|
+
sub dnEscape {
|
901
|
+
my $val = shift;
|
902
|
+
# first, remove spaces surrounding ',' and leading/trailing spaces
|
903
|
+
$val =~ s/^\s*//;
|
904
|
+
$val =~ s/\s*$//;
|
905
|
+
$val =~ s/\s*,\s*/,/g;
|
906
|
+
# next, replace the special characters
|
907
|
+
foreach my $idx (keys %dnspecial) {
|
908
|
+
$val =~ s/$idx/$dnspecial{$idx}/g;
|
909
|
+
}
|
910
|
+
$val =~ s/\s*,\s*/,/g;
|
911
|
+
|
912
|
+
return $val;
|
913
|
+
}
|
914
|
+
|
915
|
+
sub getHashedPassword {
|
916
|
+
my $pwd = shift;
|
917
|
+
my $alg = shift;
|
918
|
+
|
919
|
+
if ($pwd =~ /^\{\w+\}.+/) {
|
920
|
+
return $pwd; # already hashed
|
921
|
+
}
|
922
|
+
|
923
|
+
my $cmd = "/usr/bin/pwdhash";
|
924
|
+
if ($alg) {
|
925
|
+
$cmd .= " -s $alg";
|
926
|
+
}
|
927
|
+
$cmd .= " -- " . shellEscape($pwd);
|
928
|
+
my $hashedpwd = `$cmd`;
|
929
|
+
chomp($hashedpwd);
|
930
|
+
|
931
|
+
return $hashedpwd;
|
932
|
+
}
|
933
|
+
|
934
|
+
# this creates an Inf suitable for passing to createDSInstance
|
935
|
+
# except that it has a bogus suffix
|
936
|
+
sub createInfFromConfig {
|
937
|
+
my $configdir = shift;
|
938
|
+
my $inst = shift;
|
939
|
+
my $errs = shift;
|
940
|
+
my $fname = "$configdir/dse.ldif";
|
941
|
+
my $id;
|
942
|
+
($id = $inst) =~ s/^slapd-//;
|
943
|
+
if (! -f $fname || ! -r $fname) {
|
944
|
+
push @{$errs}, "error_opening_dseldif", $fname, $!;
|
945
|
+
return 0;
|
946
|
+
}
|
947
|
+
my $conn = new FileConn($fname, 1);
|
948
|
+
if (!$conn) {
|
949
|
+
push @{$errs}, "error_opening_dseldif", $fname, $!;
|
950
|
+
return 0;
|
951
|
+
}
|
952
|
+
|
953
|
+
my $ent = $conn->search("cn=config", "base", "(objectclass=*)");
|
954
|
+
if (!$ent) {
|
955
|
+
push @{$errs}, "error_opening_dseldif", $fname, $!;
|
956
|
+
$conn->close();
|
957
|
+
return 0;
|
958
|
+
}
|
959
|
+
|
960
|
+
my $inf = new Inf();
|
961
|
+
$inf->{General}->{FullMachineName} = $ent->getValues('nsslapd-localhost');
|
962
|
+
$inf->{General}->{SuiteSpotUserID} = $ent->getValues('nsslapd-localuser');
|
963
|
+
$inf->{slapd}->{RootDN} = $ent->getValues('nsslapd-rootdn');
|
964
|
+
$inf->{slapd}->{RootDNPwd} = $ent->getValues('nsslapd-rootpw');
|
965
|
+
$inf->{slapd}->{ServerPort} = $ent->getValues('nsslapd-port');
|
966
|
+
$inf->{slapd}->{ServerIdentifier} = $id;
|
967
|
+
|
968
|
+
my $suffix = "";
|
969
|
+
$ent = $conn->search("cn=ldbm database,cn=plugins,cn=config",
|
970
|
+
"one", "(objectclass=*)");
|
971
|
+
if (!$ent) {
|
972
|
+
push @{$errs}, "error_opening_dseldif", $fname, $!;
|
973
|
+
$conn->close();
|
974
|
+
return 0;
|
975
|
+
}
|
976
|
+
# use the userRoot suffix if available
|
977
|
+
while ($ent) {
|
978
|
+
if ($ent->getValues('nsslapd-suffix')) {
|
979
|
+
$suffix = $ent->getValues('nsslapd-suffix');
|
980
|
+
}
|
981
|
+
last if ($ent->hasValue('cn', 'userRoot', 1));
|
982
|
+
$ent = $conn->nextEntry();
|
983
|
+
}
|
984
|
+
if ( "" eq "$suffix" )
|
985
|
+
{
|
986
|
+
push @{$errs}, "error_opening_dseldif", $fname, $!;
|
987
|
+
$conn->close();
|
988
|
+
return 0;
|
989
|
+
}
|
990
|
+
|
991
|
+
# we also need the instance dir
|
992
|
+
$ent = $conn->search("cn=config", "base", "(objectclass=*)");
|
993
|
+
if (!$ent) {
|
994
|
+
push @{$errs}, "error_opening_dseldif", $fname, $!;
|
995
|
+
$conn->close();
|
996
|
+
return 0;
|
997
|
+
}
|
998
|
+
my $inst_dir = $ent->getValue('nsslapd-instancedir');
|
999
|
+
|
1000
|
+
$conn->close();
|
1001
|
+
|
1002
|
+
if ($inst_dir) {
|
1003
|
+
$inf->{slapd}->{inst_dir} = $inst_dir;
|
1004
|
+
}
|
1005
|
+
$inf->{slapd}->{Suffix} = $suffix;
|
1006
|
+
|
1007
|
+
return $inf;
|
1008
|
+
}
|
1009
|
+
|
1010
|
+
# like File::Path mkpath, except we can set the owner and perm
|
1011
|
+
# of each new path and parent path created
|
1012
|
+
sub makePaths {
|
1013
|
+
my ($path, $mode, $user, $group) = @_;
|
1014
|
+
my $uid = getpwnam $user;
|
1015
|
+
my $gid = -1; # default to leave it alone
|
1016
|
+
my $mode_string = "";
|
1017
|
+
|
1018
|
+
if ($group) {
|
1019
|
+
$gid = getgrnam $group;
|
1020
|
+
}
|
1021
|
+
my @dirnames = ($path);
|
1022
|
+
my $parent = $path;
|
1023
|
+
for ($parent = dirname($parent);
|
1024
|
+
$parent and ($parent ne "/");
|
1025
|
+
$parent = dirname($parent)) {
|
1026
|
+
unshift @dirnames, $parent;
|
1027
|
+
}
|
1028
|
+
for my $dir (@dirnames) {
|
1029
|
+
next if (-d $dir);
|
1030
|
+
$! = 0; # clear
|
1031
|
+
mkdir $dir, $mode;
|
1032
|
+
if ($!) {
|
1033
|
+
return ('error_creating_directory', $dir, $!);
|
1034
|
+
}
|
1035
|
+
chown $uid, $gid, $dir;
|
1036
|
+
if ($!) {
|
1037
|
+
return ('error_chowning_directory', $dir, $!);
|
1038
|
+
}
|
1039
|
+
chmod $mode, $dir;
|
1040
|
+
$mode_string = sprintf "%lo", $mode;
|
1041
|
+
debug(1, "makePaths: created directory $dir mode $mode_string user $user group $group\n");
|
1042
|
+
debug(2, "\t" . `ls -ld $dir`);
|
1043
|
+
}
|
1044
|
+
|
1045
|
+
return ();
|
1046
|
+
}
|
1047
|
+
|
1048
|
+
# remove_tree($centry, $key, $instname, [$isparent, [$dontremove]])
|
1049
|
+
# $centry: entry to look for the path to be removed
|
1050
|
+
# $key: key to look for the path in the entry
|
1051
|
+
# $instname: instance name "slapd-<ID>" to check the path
|
1052
|
+
# $isparent: specify 1 to remove from the parent dir
|
1053
|
+
# $dontremove: pattern not to be removed (e.g., ".db$")
|
1054
|
+
sub remove_tree
|
1055
|
+
{
|
1056
|
+
my $centry = shift;
|
1057
|
+
my $key = shift;
|
1058
|
+
my $instname = shift;
|
1059
|
+
my $isparent = shift;
|
1060
|
+
my $dontremove = shift;
|
1061
|
+
my @errs = (); # a list of array refs - each array ref is suitable for passing to Resource::getText
|
1062
|
+
|
1063
|
+
foreach my $path ( @{$centry->{$key}} )
|
1064
|
+
{
|
1065
|
+
my $rmdir = "";
|
1066
|
+
my $rc = 0;
|
1067
|
+
if ( 1 == $isparent )
|
1068
|
+
{
|
1069
|
+
$rmdir = dirname($path);
|
1070
|
+
}
|
1071
|
+
else
|
1072
|
+
{
|
1073
|
+
$rmdir = $path;
|
1074
|
+
}
|
1075
|
+
if ( -d $rmdir && $rmdir =~ /$instname/ )
|
1076
|
+
{
|
1077
|
+
if ( "" eq "$dontremove" )
|
1078
|
+
{
|
1079
|
+
$rc = rmtree($rmdir);
|
1080
|
+
if ( 0 == $rc )
|
1081
|
+
{
|
1082
|
+
push @errs, [ 'error_removing_path', $rmdir, $! ];
|
1083
|
+
debug(1, "Warning: $rmdir was not removed. Error: $!\n");
|
1084
|
+
}
|
1085
|
+
}
|
1086
|
+
else
|
1087
|
+
{
|
1088
|
+
# Skip the dontremove files
|
1089
|
+
$rc = opendir(DIR, $rmdir);
|
1090
|
+
if ($rc)
|
1091
|
+
{
|
1092
|
+
while (defined(my $file = readdir(DIR)))
|
1093
|
+
{
|
1094
|
+
next if ( "$file" =~ /$dontremove/ );
|
1095
|
+
next if ( "$file" eq "." );
|
1096
|
+
next if ( "$file" eq ".." );
|
1097
|
+
my $rmfile = $rmdir . "/" . $file;
|
1098
|
+
my $rc0 = rmtree($rmfile);
|
1099
|
+
if ( 0 == $rc0 )
|
1100
|
+
{
|
1101
|
+
push @errs, [ 'error_removing_path', $rmfile, $! ];
|
1102
|
+
debug(1, "Warning: $rmfile was not removed. Error: $!\n");
|
1103
|
+
}
|
1104
|
+
}
|
1105
|
+
closedir(DIR);
|
1106
|
+
}
|
1107
|
+
my $newrmdir = $rmdir . ".removed";
|
1108
|
+
my $rc1 = 1;
|
1109
|
+
if ( -d $newrmdir )
|
1110
|
+
{
|
1111
|
+
$rc1 = rmtree($newrmdir);
|
1112
|
+
if ( 0 == $rc1 )
|
1113
|
+
{
|
1114
|
+
push @errs, [ 'error_removing_path', $newrmdir, $! ];
|
1115
|
+
debug(1, "Warning: $newrmdir was not removed. Error: $!\n");
|
1116
|
+
}
|
1117
|
+
}
|
1118
|
+
if ( 0 < $rc1 )
|
1119
|
+
{
|
1120
|
+
rename($rmdir, $newrmdir);
|
1121
|
+
}
|
1122
|
+
}
|
1123
|
+
}
|
1124
|
+
}
|
1125
|
+
|
1126
|
+
return @errs; # a list of array refs - if (!@errs) then success
|
1127
|
+
}
|
1128
|
+
|
1129
|
+
sub remove_pidfile
|
1130
|
+
{
|
1131
|
+
my ($type, $serv_id, $instdir, $instname, $run_dir, $product_name) = @_;
|
1132
|
+
my $pidfile;
|
1133
|
+
|
1134
|
+
# Construct the pidfile name as follows:
|
1135
|
+
# PIDFILE=$RUN_DIR/$PRODUCT_NAME-$SERV_ID.pid
|
1136
|
+
# STARTPIDFILE=$RUN_DIR/$PRODUCT_NAME-$SERV_ID.startpid
|
1137
|
+
if ($type eq "PIDFILE") {
|
1138
|
+
$pidfile = $run_dir . "/" . $product_name . "-" . $serv_id . ".pid";
|
1139
|
+
} elsif ($type eq "STARTPIDFILE") {
|
1140
|
+
$pidfile = $run_dir . "/" . $product_name . "-" . $serv_id . ".startpid";
|
1141
|
+
}
|
1142
|
+
|
1143
|
+
if ( -e $pidfile && $pidfile =~ /$instname/ )
|
1144
|
+
{
|
1145
|
+
unlink($pidfile);
|
1146
|
+
}
|
1147
|
+
}
|
1148
|
+
|
1149
|
+
sub serverIsRunning
|
1150
|
+
{
|
1151
|
+
my ($run_dir, $inst) = @_;
|
1152
|
+
my $pidfile = $run_dir . "/" . $inst . ".pid";
|
1153
|
+
if ( -e $pidfile ) {
|
1154
|
+
if (!open(PIDFILE, $pidfile)) {
|
1155
|
+
debug(3, "Could not open pidfile $pidfile - $! - assume server is not running\n");
|
1156
|
+
return 0; # could not open pid file - assume server is not running
|
1157
|
+
}
|
1158
|
+
my $pid = <PIDFILE>;
|
1159
|
+
chomp($pid);
|
1160
|
+
close(PIDFILE);
|
1161
|
+
if (!$pid) {
|
1162
|
+
debug(3, "Bogus pid $pid found in pidfile $pidfile - assume server is not running\n");
|
1163
|
+
return 0; # could not open pid file - assume server is not running
|
1164
|
+
}
|
1165
|
+
if (kill(0, $pid)) {
|
1166
|
+
debug(3, "pid $pid from file $pidfile is running\n");
|
1167
|
+
return 1; # server is running
|
1168
|
+
}
|
1169
|
+
debug(3, "pid $pid from file $pidfile is not running - could not kill 0 - $!\n");
|
1170
|
+
} else {
|
1171
|
+
debug(3, "No such file pidfile $pidfile - $! - assume server is not running\n");
|
1172
|
+
}
|
1173
|
+
|
1174
|
+
return 0; # no pid file - assume not running
|
1175
|
+
}
|
1176
|
+
|
1177
|
+
sub libpath_add {
|
1178
|
+
my $libpath = shift;
|
1179
|
+
|
1180
|
+
if ($libpath) {
|
1181
|
+
if ($ENV{'LD_LIBRARY_PATH'}) {
|
1182
|
+
$ENV{'LD_LIBRARY_PATH'} = "$ENV{'LD_LIBRARY_PATH'}:$libpath";
|
1183
|
+
} else {
|
1184
|
+
$ENV{'LD_LIBRARY_PATH'} = "$libpath";
|
1185
|
+
}
|
1186
|
+
}
|
1187
|
+
}
|
1188
|
+
|
1189
|
+
#
|
1190
|
+
# get_info()
|
1191
|
+
#
|
1192
|
+
# Grab all the config settings we need from the dse.ldif
|
1193
|
+
#
|
1194
|
+
sub get_info {
|
1195
|
+
my %info = ();
|
1196
|
+
my $dir = shift;
|
1197
|
+
$info{host} = shift;
|
1198
|
+
$info{port} = shift;
|
1199
|
+
$info{rootdn} = shift;
|
1200
|
+
my $dse_file = "$dir/dse.ldif";
|
1201
|
+
my $foundcfg = "no";
|
1202
|
+
my $value;
|
1203
|
+
my $entry;
|
1204
|
+
my $ldif;
|
1205
|
+
|
1206
|
+
#
|
1207
|
+
# Are we using openLDAP or Mozilla?
|
1208
|
+
#
|
1209
|
+
my $toollib = `ldapsearch -V 2>&1`;
|
1210
|
+
if ($toollib =~ /OpenLDAP/) {
|
1211
|
+
$info{openldap} = "yes";
|
1212
|
+
$info{nofold} = "-o ldif-wrap=no";
|
1213
|
+
} else {
|
1214
|
+
$info{openldap} = "no";
|
1215
|
+
$info{nofold} = "-T";
|
1216
|
+
}
|
1217
|
+
|
1218
|
+
#
|
1219
|
+
# Open dse.ldif and grab the cn=config entry
|
1220
|
+
#
|
1221
|
+
open(DSE, "$dse_file") || die "Failed to open config file $dse_file $!\n";
|
1222
|
+
$ldif = new Mozilla::LDAP::LDIF(*DSE);
|
1223
|
+
while($entry = readOneEntry $ldif){
|
1224
|
+
if($entry->getDN() eq "cn=config"){
|
1225
|
+
$foundcfg = "yes";
|
1226
|
+
last;
|
1227
|
+
}
|
1228
|
+
}
|
1229
|
+
if($foundcfg eq "no"){
|
1230
|
+
print (STDERR "Failed to find \"cn=config\" entry from $dse_file\n");
|
1231
|
+
close (DSE);
|
1232
|
+
exit 1;
|
1233
|
+
}
|
1234
|
+
|
1235
|
+
#
|
1236
|
+
# Get missing info
|
1237
|
+
#
|
1238
|
+
if($info{host} eq ""){
|
1239
|
+
$info{host} = $entry->getValues("nsslapd-localhost");
|
1240
|
+
}
|
1241
|
+
if($info{port} eq ""){
|
1242
|
+
$info{port} = $entry->getValues("nsslapd-port") || "389";
|
1243
|
+
}
|
1244
|
+
if($info{rootdn} eq ""){
|
1245
|
+
$info{rootdn} = $entry->getValues("nsslapd-rootdn");
|
1246
|
+
}
|
1247
|
+
|
1248
|
+
#
|
1249
|
+
# Get SSL and LDAPI settings
|
1250
|
+
#
|
1251
|
+
$info{certdir} = $entry->getValues("nsslapd-certdir");
|
1252
|
+
if($info{openldap} eq "yes"){
|
1253
|
+
$ENV{LDAPTLS_CACERTDIR}=$info{certdir};
|
1254
|
+
}
|
1255
|
+
$info{security} = $entry->getValues("nsslapd-security");
|
1256
|
+
$info{secure_port} = $entry->getValues("nsslapd-securePort") || "636";
|
1257
|
+
$info{ldapi} = $entry->getValues("nsslapd-ldapilisten");
|
1258
|
+
$info{autobind} = $entry->getValues("nsslapd-ldapiautobind");
|
1259
|
+
$value = $entry->getValues("nsslapd-ldapifilepath");
|
1260
|
+
if ($value){
|
1261
|
+
$value =~ s/\//%2f/g;
|
1262
|
+
$info{ldapiURL} = "ldapi://" . $value;
|
1263
|
+
}
|
1264
|
+
|
1265
|
+
while($entry = readOneEntry $ldif){
|
1266
|
+
if($entry->getDN() eq "cn=encryption,cn=config"){
|
1267
|
+
$foundcfg = "yes";
|
1268
|
+
last;
|
1269
|
+
}
|
1270
|
+
}
|
1271
|
+
if($foundcfg eq "yes" && $entry){
|
1272
|
+
$info{cacertfile} = $entry->getValues("CACertExtractFile");
|
1273
|
+
if ($info{cacertfile}) {
|
1274
|
+
$ENV{LDAPTLS_CACERT}=$info{cacertfile};
|
1275
|
+
}
|
1276
|
+
}
|
1277
|
+
|
1278
|
+
close (DSE);
|
1279
|
+
return %info;
|
1280
|
+
}
|
1281
|
+
|
1282
|
+
#
|
1283
|
+
# return the normalized server id and the server config dir (contains dse.ldif)
|
1284
|
+
#
|
1285
|
+
sub get_server_id {
|
1286
|
+
my $servid = shift;
|
1287
|
+
my $dir = shift;
|
1288
|
+
my $instance_count = 0;
|
1289
|
+
my $first = "yes";
|
1290
|
+
my $instances = "<none>";
|
1291
|
+
my $name;
|
1292
|
+
my $inst;
|
1293
|
+
my $file;
|
1294
|
+
my @extra = ();
|
1295
|
+
my $extradir = "";
|
1296
|
+
|
1297
|
+
if (getLogin ne 'root') {
|
1298
|
+
$extradir = "$ENV{HOME}/.dirsrv";
|
1299
|
+
if (-d $extradir) {
|
1300
|
+
opendir(EXTRADIR, $extradir);
|
1301
|
+
@extra = map {$_ = "$extradir/$_"} readdir(EXTRADIR);
|
1302
|
+
closedir(EXTRADIR);
|
1303
|
+
}
|
1304
|
+
}
|
1305
|
+
|
1306
|
+
if (defined $ENV{INITCONFIGDIR}) {
|
1307
|
+
$dir = $ENV{INITCONFIGDIR};
|
1308
|
+
@extra = (); # only use what was provided
|
1309
|
+
$extradir = "";
|
1310
|
+
}
|
1311
|
+
|
1312
|
+
# normalize the given servid
|
1313
|
+
if (!$servid) {
|
1314
|
+
# not given
|
1315
|
+
} elsif ($servid =~ /^dirsrv-/){
|
1316
|
+
# strip off "dirsrv-"
|
1317
|
+
$servid =~ s/^dirsrv-//;
|
1318
|
+
} elsif ($servid =~ /^slapd-/){
|
1319
|
+
# strip off "slapd-"
|
1320
|
+
$servid =~ s/^slapd-//;
|
1321
|
+
} # else assume already normalized
|
1322
|
+
|
1323
|
+
opendir(DIR, "$dir");
|
1324
|
+
my @files = map {$_ = "$dir/$_"} readdir(DIR);
|
1325
|
+
closedir(DIR);
|
1326
|
+
push @files, @extra;
|
1327
|
+
my $found = 0;
|
1328
|
+
foreach $file (@files){
|
1329
|
+
next if(! -r $file); # skip unreadable files
|
1330
|
+
# skip admin server
|
1331
|
+
if($file =~ m,/dirsrv-([^/]+)$, && $file !~ m,/dirsrv-admin$,){
|
1332
|
+
$name = $file;
|
1333
|
+
$inst = $1;
|
1334
|
+
$instance_count++;
|
1335
|
+
if ($servid && ($servid eq $inst)) {
|
1336
|
+
$found = 1;
|
1337
|
+
last;
|
1338
|
+
}
|
1339
|
+
if($first eq "yes"){
|
1340
|
+
$instances=$inst;
|
1341
|
+
$first = "no";
|
1342
|
+
} else {
|
1343
|
+
$instances=$instances . ", $inst";
|
1344
|
+
}
|
1345
|
+
}
|
1346
|
+
}
|
1347
|
+
|
1348
|
+
if ($servid && !$found) { # if we got here, did not find given serverid
|
1349
|
+
print (STDERR "Invalid server identifer: $servid\n");
|
1350
|
+
print (STDERR "Available instances in $dir $extradir: $instances\n");
|
1351
|
+
exit (1);
|
1352
|
+
}
|
1353
|
+
|
1354
|
+
if ($instance_count == 0){
|
1355
|
+
print "No instances found in $dir\n";
|
1356
|
+
exit (1);
|
1357
|
+
}
|
1358
|
+
|
1359
|
+
if (!$servid && $instance_count > 1){
|
1360
|
+
print "You must supply a valid server instance identifier. Use -Z to specify instance name\n";
|
1361
|
+
print "Available instances: $instances\n";
|
1362
|
+
exit (1);
|
1363
|
+
}
|
1364
|
+
unless ( -e "$name" ){
|
1365
|
+
print (STDERR "Invalid server identifer: $servid\n");
|
1366
|
+
print (STDERR "Available instances in $dir $extradir: $instances\n");
|
1367
|
+
exit (1);
|
1368
|
+
}
|
1369
|
+
|
1370
|
+
# now grab the CONFIG_DIR from the file $name
|
1371
|
+
if (!open(INSTFILE, "$name")) {
|
1372
|
+
print (STDERR "Error: could not open $name: ");
|
1373
|
+
exit (1);
|
1374
|
+
}
|
1375
|
+
|
1376
|
+
my $confdir;
|
1377
|
+
while (<INSTFILE>) {
|
1378
|
+
if (/^CONFIG_DIR=/) {
|
1379
|
+
s/^CONFIG_DIR=//;
|
1380
|
+
s/ ; export CONFIG_DIR//;
|
1381
|
+
$confdir = $_;
|
1382
|
+
chomp($confdir);
|
1383
|
+
last;
|
1384
|
+
}
|
1385
|
+
}
|
1386
|
+
close INSTFILE;
|
1387
|
+
|
1388
|
+
if (!$confdir) {
|
1389
|
+
print (STDERR "Error: no CONFIG_DIR found in $name\n");
|
1390
|
+
exit (1);
|
1391
|
+
}
|
1392
|
+
|
1393
|
+
return ($inst, $confdir);
|
1394
|
+
}
|
1395
|
+
|
1396
|
+
#
|
1397
|
+
# Get the root DN password from the file, or command line input
|
1398
|
+
#
|
1399
|
+
sub get_password_from_file {
|
1400
|
+
my $passwd = shift;
|
1401
|
+
my $passwdfile = shift;
|
1402
|
+
|
1403
|
+
if ($passwdfile ne ""){
|
1404
|
+
# Open file and get the password
|
1405
|
+
unless (open (RPASS, $passwdfile)) {
|
1406
|
+
die "Error, cannot open password file $passwdfile\n";
|
1407
|
+
}
|
1408
|
+
$passwd = <RPASS>;
|
1409
|
+
chomp($passwd);
|
1410
|
+
close(RPASS);
|
1411
|
+
} elsif ($passwd eq "-"){
|
1412
|
+
# Read the password from terminal
|
1413
|
+
print "Bind Password: ";
|
1414
|
+
# Disable console echo
|
1415
|
+
system("/bin/stty -echo") if -t STDIN;
|
1416
|
+
# read the answer
|
1417
|
+
$passwd = <STDIN>;
|
1418
|
+
# Enable console echo
|
1419
|
+
system("/bin/stty echo") if -t STDIN;
|
1420
|
+
print "\n";
|
1421
|
+
chop($passwd); # trim trailing newline
|
1422
|
+
}
|
1423
|
+
|
1424
|
+
return $passwd;
|
1425
|
+
}
|
1426
|
+
|
1427
|
+
#
|
1428
|
+
# Execute the ldapmodify
|
1429
|
+
#
|
1430
|
+
sub ldapmod {
|
1431
|
+
my $entry = shift;
|
1432
|
+
my %info = @_;
|
1433
|
+
my $file = "/tmp/DSUtil-$$.txt";
|
1434
|
+
my $protocol_error;
|
1435
|
+
my $result;
|
1436
|
+
my $rc;
|
1437
|
+
my $myrootdnpw = shellEscape($info{rootdnpw});
|
1438
|
+
|
1439
|
+
#
|
1440
|
+
# write the entry to file so we can grab the result code after running ldapmodify(-f)
|
1441
|
+
#
|
1442
|
+
if(!open (FILE, ">$file") ){
|
1443
|
+
print (STDERR "DSUtil::ldapmod() failed to create tmp file ($!)\n");
|
1444
|
+
return 1;
|
1445
|
+
} else {
|
1446
|
+
print (FILE "$entry\n");
|
1447
|
+
close (FILE);
|
1448
|
+
}
|
1449
|
+
|
1450
|
+
if ($info{redirect} eq ""){
|
1451
|
+
$info{redirect} = "> /dev/null";
|
1452
|
+
}
|
1453
|
+
|
1454
|
+
#
|
1455
|
+
# Check the protocol, and reset it if it's invalid
|
1456
|
+
#
|
1457
|
+
$result = check_protocol(%info);
|
1458
|
+
if($result == 1){
|
1459
|
+
$protocol_error = "yes";
|
1460
|
+
$info{protocol} = "";
|
1461
|
+
} elsif( $result == 2){
|
1462
|
+
unlink ($file);
|
1463
|
+
return 1;
|
1464
|
+
}
|
1465
|
+
|
1466
|
+
#
|
1467
|
+
# Execute ldapmodify using the specified/most secure protocol
|
1468
|
+
#
|
1469
|
+
if (($info{security} eq "on" && $info{protocol} eq "") || ($info{security} eq "on" && $info{protocol} =~ m/STARTTLS/i) ){
|
1470
|
+
#
|
1471
|
+
# STARTTLS
|
1472
|
+
#
|
1473
|
+
if($protocol_error eq "yes"){
|
1474
|
+
print "STARTTLS)\n";
|
1475
|
+
}
|
1476
|
+
if($info{openldap} eq "yes"){
|
1477
|
+
system "ldapmodify -x -ZZ -h $info{host} -p $info{port} -D \"$info{rootdn}\" -w $myrootdnpw $info{args} -f \"$file\" $info{redirect}";
|
1478
|
+
} else {
|
1479
|
+
system "ldapmodify -ZZZ -P \"$info{certdir}\" -h $info{host} -p $info{port} -D \"$info{rootdn}\" -w $myrootdnpw $info{args} -f \"$file\" $info{redirect}";
|
1480
|
+
}
|
1481
|
+
} elsif (($info{security} eq "on" && $info{protocol} eq "") || ($info{security} eq "on" && $info{protocol} =~ m/LDAPS/i) ){
|
1482
|
+
#
|
1483
|
+
# LDAPS
|
1484
|
+
#
|
1485
|
+
if($protocol_error eq "yes"){
|
1486
|
+
print "LDAPS)\n";
|
1487
|
+
}
|
1488
|
+
if($info{openldap} eq "yes"){
|
1489
|
+
system "ldapmodify -x -H \"ldaps://$info{host}:$info{secure_port}\" -D \"$info{rootdn}\" -w $myrootdnpw $info{args} -f \"$file\" $info{redirect}";
|
1490
|
+
} else {
|
1491
|
+
system "ldapmodify -Z -P \"$info{certdir}\" -p $info{secure_port} -D \"$info{rootdn}\" -w $myrootdnpw $info{args} -f \"$file\" $info{redirect}";
|
1492
|
+
}
|
1493
|
+
} elsif (($info{openldap} eq "yes") && (($info{ldapi} eq "on" && $info{protocol} eq "") || ($info{ldapi} eq "on" && $info{protocol} =~ m/LDAPI/i)) ){
|
1494
|
+
#
|
1495
|
+
# LDAPI
|
1496
|
+
#
|
1497
|
+
if ($< == 0 && $info{autobind} eq "on"){
|
1498
|
+
if($protocol_error eq "yes"){
|
1499
|
+
print "LDAPI/AUTOBIND)\n";
|
1500
|
+
}
|
1501
|
+
system "ldapmodify -H \"$info{ldapiURL}\" -Y EXTERNAL $info{args} -f \"$file\" > /dev/null 2>&1";
|
1502
|
+
} else {
|
1503
|
+
if($protocol_error eq "yes"){
|
1504
|
+
print "LDAPI)\n";
|
1505
|
+
}
|
1506
|
+
system "ldapmodify -x -H \"$info{ldapiURL}\" -D \"$info{rootdn}\" -w $myrootdnpw $info{args} -f \"$file\" $info{redirect}";
|
1507
|
+
}
|
1508
|
+
} else {
|
1509
|
+
#
|
1510
|
+
# LDAP
|
1511
|
+
#
|
1512
|
+
if($protocol_error eq "yes"){
|
1513
|
+
print "LDAP)\n";
|
1514
|
+
}
|
1515
|
+
if($info{openldap} eq "yes"){
|
1516
|
+
system "ldapmodify -x -h $info{host} -p $info{port} -D \"$info{rootdn}\" -w $myrootdnpw $info{args} -f \"$file\" $info{redirect}";
|
1517
|
+
} else {
|
1518
|
+
system "ldapmodify -h $info{host} -p $info{port} -D \"$info{rootdn}\" -w $myrootdnpw $info{args} -f \"$file\" $info{redirect}";
|
1519
|
+
}
|
1520
|
+
}
|
1521
|
+
unlink ($file);
|
1522
|
+
if ($? != 0){
|
1523
|
+
my $retCode=$?>>8;
|
1524
|
+
return $retCode;
|
1525
|
+
}
|
1526
|
+
return 0;
|
1527
|
+
}
|
1528
|
+
|
1529
|
+
#
|
1530
|
+
# Build the ldapsearch
|
1531
|
+
#
|
1532
|
+
sub ldapsrch {
|
1533
|
+
my %info = @_;
|
1534
|
+
my $protocol_error;
|
1535
|
+
my $search;
|
1536
|
+
my $result;
|
1537
|
+
my $myrootdnpw = shellEscape($info{rootdnpw});
|
1538
|
+
|
1539
|
+
$result = check_protocol(%info);
|
1540
|
+
if($result == 1){
|
1541
|
+
$protocol_error = "yes";
|
1542
|
+
$info{protocol} = "";
|
1543
|
+
} elsif( $result == 2){
|
1544
|
+
return "";
|
1545
|
+
}
|
1546
|
+
if (($info{security} eq "on" && $info{protocol} eq "") || ($info{security} eq "on" && $info{protocol} =~ m/STARTTLS/i) ){
|
1547
|
+
#
|
1548
|
+
# STARTTLS
|
1549
|
+
#
|
1550
|
+
if($protocol_error eq "yes"){
|
1551
|
+
print "STARTTLS)\n";
|
1552
|
+
}
|
1553
|
+
if($info{openldap} eq "yes"){
|
1554
|
+
$search = "ldapsearch -x -LLL -ZZ -p $info{port} -h $info{host} -D \"$info{rootdn}\" -w $myrootdnpw $info{nofold} " .
|
1555
|
+
"$info{srch_args} -b \"$info{base}\" -s $info{scope} \"$info{filter}\" $info{attrs}";
|
1556
|
+
} else {
|
1557
|
+
$search = "ldapsearch -ZZZ -P \"$info{certdir}\" -p $info{port} -h $info{host} -D \"$info{rootdn}\" $info{nofold} " .
|
1558
|
+
"-w $myrootdnpw $info{srch_args} -b \"$info{base}\" -s $info{scope} \"$info{filter}\" $info{attrs}";
|
1559
|
+
}
|
1560
|
+
} elsif (($info{security} eq "on" && $info{protocol} eq "") || ($info{security} eq "on" && $info{protocol} =~ m/LDAPS/i) ){
|
1561
|
+
#
|
1562
|
+
# LDAPS
|
1563
|
+
#
|
1564
|
+
if($protocol_error eq "yes"){
|
1565
|
+
print "LDAPS)\n";
|
1566
|
+
}
|
1567
|
+
if($info{openldap} eq "yes"){
|
1568
|
+
$search = "ldapsearch -x -LLL -H \"ldaps://$info{host}:$info{secure_port}\" -D \"$info{rootdn}\" $info{nofold} " .
|
1569
|
+
"-w $myrootdnpw $info{srch_args} -b \"$info{base}\" -s $info{scope} \"$info{filter}\" $info{attrs}";
|
1570
|
+
} else {
|
1571
|
+
$search = "ldapsearch -Z -P \"$info{certdir}\" -p $info{secure_port} -h $info{host} -D \"$info{rootdn}\" $info{nofold} " .
|
1572
|
+
"-w $myrootdnpw $info{srch_args} -b \"$info{base}\" -s $info{scope} \"$info{filter}\" $info{attrs}";
|
1573
|
+
}
|
1574
|
+
} elsif (($info{openldap} eq "yes") && (($info{ldapi} eq "on" && $info{protocol} eq "") || ($info{ldapi} eq "on" && $info{protocol} =~ m/LDAPI/i)) ){
|
1575
|
+
#
|
1576
|
+
# LDAPI
|
1577
|
+
#
|
1578
|
+
if ($< == 0 && $info{autobind} eq "on"){
|
1579
|
+
$search = "ldapsearch -LLL -H \"$info{ldapiURL}\" -Y EXTERNAL $info{nofold} " .
|
1580
|
+
"$info{srch_args} -b \"$info{base}\" -s $info{scope} \"$info{filter}\" $info{attrs} 2>/dev/null";
|
1581
|
+
} else {
|
1582
|
+
$search = "ldapsearch -x -LLL -H \"$info{ldapiURL}\" -D \"$info{rootdn}\" -w $myrootdnpw $info{nofold} " .
|
1583
|
+
"$info{srch_args} -b \"$info{base}\" -s $info{scope} \"$info{filter}\" $info{attrs}";
|
1584
|
+
}
|
1585
|
+
} else {
|
1586
|
+
#
|
1587
|
+
# LDAP
|
1588
|
+
#
|
1589
|
+
if($protocol_error eq "yes"){
|
1590
|
+
print "LDAP)\n";
|
1591
|
+
}
|
1592
|
+
if($info{openldap} eq "yes"){
|
1593
|
+
$search = "ldapsearch -x -LLL -p $info{port} -h $info{host} -D \"$info{rootdn}\" -w $myrootdnpw $info{nofold} " .
|
1594
|
+
"$info{srch_args} -b \"$info{base}\" -s $info{scope} \"$info{filter}\" $info{attrs}";
|
1595
|
+
} else {
|
1596
|
+
$search = "ldapsearch -p $info{port} -h $info{host} -D \"$info{rootdn}\" -w $myrootdnpw $info{nofold} " .
|
1597
|
+
"$info{srch_args} -b \"$info{base}\" -s $info{scope} \"$info{filter}\" $info{attrs}";
|
1598
|
+
}
|
1599
|
+
}
|
1600
|
+
return $search;
|
1601
|
+
}
|
1602
|
+
|
1603
|
+
#
|
1604
|
+
# Execute the search
|
1605
|
+
#
|
1606
|
+
sub ldapsrch_ext {
|
1607
|
+
my %info = @_;
|
1608
|
+
my $protocol_error;
|
1609
|
+
my $result;
|
1610
|
+
my $txt;
|
1611
|
+
my $myrootdnpw = shellEscape($info{rootdnpw});
|
1612
|
+
|
1613
|
+
$result = check_protocol(%info);
|
1614
|
+
if($result == 1){
|
1615
|
+
$protocol_error = "yes";
|
1616
|
+
$info{protocol} = "";
|
1617
|
+
} elsif($result == 2){
|
1618
|
+
return 1;
|
1619
|
+
}
|
1620
|
+
if (($info{security} eq "on" && $info{protocol} eq "") || ($info{security} eq "on" && $info{protocol} =~ m/STARTTLS/i) ){
|
1621
|
+
#
|
1622
|
+
# STARTTLS
|
1623
|
+
#
|
1624
|
+
if($protocol_error eq "yes"){
|
1625
|
+
print "STARTTLS)\n";
|
1626
|
+
}
|
1627
|
+
if($info{openldap} eq "yes"){
|
1628
|
+
return `ldapsearch -x -LLL -ZZ -p $info{port} -h $info{host} -D \"$info{rootdn}\" -w $myrootdnpw $info{nofold} $info{srch_args} -b \"$info{base}\" -s $info{scope} \"$info{filter}\" $info{attrs} $info{redirect}`;
|
1629
|
+
} else {
|
1630
|
+
return `ldapsearch -ZZZ -P $info{certdir} -p $info{port} -h $info{host} -D \"$info{rootdn}\" -w $myrootdnpw $info{nofold} $info{srch_args} -b \"$info{base}\" -s $info{scope} \"$info{filter}\" $info{attrs} $info{redirect}`;
|
1631
|
+
}
|
1632
|
+
} elsif (($info{security} eq "on" && $info{protocol} eq "") || ($info{security} eq "on" && $info{protocol} =~ m/LDAPS/i) ){
|
1633
|
+
#
|
1634
|
+
# LDAPS
|
1635
|
+
#
|
1636
|
+
if($protocol_error eq "yes"){
|
1637
|
+
print "LDAPS)\n";
|
1638
|
+
}
|
1639
|
+
if($info{openldap} eq "yes"){
|
1640
|
+
return `ldapsearch -x -LLL -H ldaps://$info{host}:$info{secure_port} -D \"$info{rootdn}\" -w $myrootdnpw $info{nofold} $info{srch_args} -b \"$info{base}\" -s $info{scope} \"$info{filter}\" $info{attrs} $info{redirect}`;
|
1641
|
+
} else {
|
1642
|
+
return `ldapsearch -Z -P $info{certdir} -p $info{secure_port} -D \"$info{rootdn}\" -w $myrootdnpw $info{nofold} $info{srch_args} -b \"$info{base}\" -s $info{scope} \"$info{filter}\" $info{attrs} $info{redirect}`;
|
1643
|
+
}
|
1644
|
+
} elsif (($info{openldap} eq "yes") && (($info{ldapi} eq "on" && $info{protocol} eq "") || ($info{ldapi} eq "on" && $info{protocol} =~ m/LDAPI/i)) ){
|
1645
|
+
#
|
1646
|
+
# LDAPI
|
1647
|
+
#
|
1648
|
+
if ($< == 0 && $info{autobind} eq "on"){
|
1649
|
+
return `ldapsearch -LLL -H \"$info{ldapiURL}\" -Y EXTERNAL $info{nofold} $info{srch_args} -b \"$info{base}\" -s $info{scope} \"$info{filter}\" $info{attrs} $info{redirect} 2>/dev/null`;
|
1650
|
+
} else {
|
1651
|
+
return `ldapsearch -x -LLL -H \"$info{ldapiURL}\" -D \"$info{rootdn}\" -w $myrootdnpw $info{nofold} $info{srch_args} -b \"$info{base}\" -s $info{scope} \"$info{filter}\" $info{attrs} $info{redirect}`;
|
1652
|
+
}
|
1653
|
+
} else {
|
1654
|
+
#
|
1655
|
+
# LDAP
|
1656
|
+
#
|
1657
|
+
if($protocol_error eq "yes"){
|
1658
|
+
print "LDAP)\n";
|
1659
|
+
}
|
1660
|
+
if($info{openldap} eq "yes"){
|
1661
|
+
return `ldapsearch -x -LLL -p $info{port} -h $info{host} -D \"$info{rootdn}\" -w $myrootdnpw $info{nofold} $info{srch_args} -b \"$info{base}\" -s $info{scope} \"$info{filter}\" $info{attrs} $info{redirect}`;
|
1662
|
+
} else {
|
1663
|
+
return `ldapsearch -p $info{port} -h $info{host} -D \"$info{rootdn}\" -w $myrootdnpw $info{nofold} $info{srch_args} -b \"$info{base}\" -s $info{scope} \"$info{filter}\" $info{attrs} $info{redirect}`;
|
1664
|
+
}
|
1665
|
+
}
|
1666
|
+
}
|
1667
|
+
|
1668
|
+
#
|
1669
|
+
# Check to see if the protocol is supported.
|
1670
|
+
#
|
1671
|
+
# If it's not supported, start logging the error message - the
|
1672
|
+
# message will be completed by the calling function.
|
1673
|
+
#
|
1674
|
+
sub check_protocol {
|
1675
|
+
my %info = @_;
|
1676
|
+
my $txt;
|
1677
|
+
|
1678
|
+
if(($info{protocol} eq "LDAPI" && $info{openldap} eq "no") ||
|
1679
|
+
($info{protocol} eq "LDAPI" && $info{ldapi} eq "off") ||
|
1680
|
+
($info{protocol} eq "STARTTLS" && ($info{security} eq "" || $info{security} eq "off")) ||
|
1681
|
+
($info{protocol} eq "LDAPS" && ($info{security} eq "" || $info{security} eq "off"))
|
1682
|
+
){
|
1683
|
+
if($info{protocol} eq "LDAPI" && $info{openldap} eq "no"){
|
1684
|
+
$txt = " by the Mozilla LDAP client";
|
1685
|
+
} else {
|
1686
|
+
$txt = " by the Directory Server";
|
1687
|
+
}
|
1688
|
+
print (STDERR "Protocol $info{protocol} requested, but this protocol is not supported" . $txt . ".\n" .
|
1689
|
+
"Using the next most secure protocol (" ); # completed by the caller
|
1690
|
+
return 1;
|
1691
|
+
}
|
1692
|
+
if( ($info{protocol} ne "") && ($info{protocol} ne "STARTTLS" &&
|
1693
|
+
$info{protocol} ne "LDAPS" &&
|
1694
|
+
$info{protocol} ne "LDAPI" &&
|
1695
|
+
$info{protocol} ne "LDAP") )
|
1696
|
+
{
|
1697
|
+
print (STDERR "Unknown protocol: $info{protocol}\n");
|
1698
|
+
return 2;
|
1699
|
+
}
|
1700
|
+
return 0;
|
1701
|
+
}
|
1702
|
+
|
1703
|
+
1;
|
1704
|
+
|
1705
|
+
# emacs settings
|
1706
|
+
# Local Variables:
|
1707
|
+
# mode:perl
|
1708
|
+
# indent-tabs-mode: nil
|
1709
|
+
# tab-width: 4
|
1710
|
+
# End:
|