This file is indexed.

/usr/share/goto/ldap_get_object is in goto-common 3.1-1.1.

This file is owned by root:root, with mode 0o755.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
#!/usr/bin/perl -l -s
# Copyright (c) 2008 Landeshauptstadt München
#
# Author: Matthias S. Benkmann
#
# 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, see <http://www.gnu.org/licenses/>.

use strict;
use warnings;

use lib ("/usr/lib/goto");
use Net::LDAP;
use Net::LDAP::Util qw(escape_filter_value ldap_explode_dn);
use GOto::LDAP qw(ldap_get_object printEntry printAttribute);
use GOto::Common qw(:ldap);

{ # main()
our ($user, $timeout, $filter, $debug, $object, $enctrigger, $format, 
$subquery, $sublevel, $subconflict, $sort);

my $USAGE = "USAGE: ldap_get_object
-debug 
-user=<user> -object=<objectClass>/<cn/ou> -filter=<filter> 
-timeout=<seconds>
-subquery=<filter> -sublevel=<level> -subconflict=<level>
-enctrigger=<regex> -format=a:v|v 
-sort=alpha|precedence
attributeRegex [attributeRegex ...]

Primary usage:
  Searches the LDAP directory for information about the user identified by 
  <user> (defaults to the environment variable \$USER). 
  Information may come from the user's own node,
  a posix group the user belongs to, an object group the user belongs to
  or an object group that includes a posix group that the user belongs to.

  Each attributeRegex is a regular expression that selects all attributes with
  matching names for output. The 1st character of attributeRegex determines what
  happens if different nodes (e.g. the user's posixAccount and a posixGroup)
  provide an attribute with the same name. 
  If attributeRegex starts with \@, then the attributes will be merged 
  (i.e. the result will include all values).
  If attributeRegex does NOT start with \@, then an attribute from the user's
  posixAccount node beats a posix group, which beats an object group that
  includes the user which beats an object group that contains a posix group.
  This determination is done individually for each of the selected attributes,
  so the output of this program may be a mixture of information from
  different sources. 
  If 2 sources with the same precedence (e.g. 2 posix groups) provide an attribute
  of the same name, selected by an attributeRegex that doesn't start with \@,
  a WARNING is signalled and the program picks one of the conflicting
  attributes.
  If multiple attributeRegexes match the same attribute, the 1st matching
  attributeRegex determines conflict resolution.
  If no attributeRegex is specified, all attributes will be merged and output.
  
Alternative usage:
  Instead of searching for user information, you can pass 
  -object=<objectClass>/<cn/ou> and the program will give information on the object
  with the given object class and the given CN or OU (if no object with the 
  CN exists).

attributeRegexes are always matched against the complete attribute name, i.e.
an attributeRegex \"name\" will NOT match an attribute \"surname\".
Matching is always performed case-insensitive.

If there is more than 1 posixAccount node for the given user id, the program 
will exit with an error.

If -timeout is passed, LDAP requests will use a timeout of <seconds> seconds.
Note that this does *not* mean that ldap_get_object will finish
within this time limit, since several LDAP requests may be involved.
Default timeout is 10s.

-filter is an LDAP-Expression that will be ANDed with all user/object/group
searches done by this program (use this to select by gosaUnitTag).

The -subquery parameter allows treating the contents of subtrees of 
the user/object/group nodes as if they were attributes of the node
itself. The names of these pseudo-attributes  have the form
\"foo/bar/attr\". The <filter> (e.g. \"objectClass=foo\") 
selects the sub-tree nodes whose attributes should be pulled in.

  -sublevel specifies the maximum number of slashes the pseudo-attribute
  names will contain. If the complete name of a pseudo-attribute 
  has more slashes than <level> the name will be shortened to the longest
  suffix that contains <level> slashes. Specifying -sublevel=0 will
  effectively merge all subquery nodes with the user/object/group node
  so that in the end result their attributes are indistinguishable from
  those of the user/object/group node. Default -sublevel is 9999.
  Note: attributeRegex matching is performed on the full name with 
  all slashes.

  -subconflict determines when 2 pseudo-attributes are treated as being
  in conflict with each other. 2 pseudo-attributes are treated as
  conflicting if the results of removing the shortest suffixes containing
  <level> slashes from their names (shortened according to -sublevel) 
  are identical. E.g. with -subconflict=0
  the pseudo-attributes \"foo/bar\" and \"foo/bla\" are not conflicting,
  whereas with -subconflict=1 they are. Default -subconflict is 1.

If -enctrigger is set, all DNs and attribute values will be tested against
the given <regex>. Whenever a value matches the <regex> it will be output
base64 encoded. Matching is performed case-sensitive and unless ^ and \$ are
used in the regex, matching substrings are enough to trigger encoding.
If no -enctrigger is specified, the default \"[\\x00-\\x1f]\" is used.
If you pass -enctrigger=none, encoding will be completely disabled.

-format specifies the output format. Format \"a:v\" means to print 
\"attributeName: value\" pairs. Format \"v\" means to print the values only.

-sort allows you to change the order in which attributes are printed. With
-sort=alpha (default) all attributes are printed in alphabetical order of the
attribute names. With -sort=precedence attributes from sources with lower 
precedence will be printed before those with higher precedence. 
Within each group, alphabetical order is used. 
The exception is the DN which is always first (if selected at all).
-sort=precedence does not affect attributes
that are not merged (because only one value is printed for those).
If an attribute has multiple values (from the same source), they will all be
output in alphabetical order. Unless -sort=precedence is selected, 
duplicate values will be printed only once.

";

if (!defined($user) and !defined($object) and !defined($enctrigger) and !defined($timeout) 
and !defined($filter) and !defined($sublevel) and !defined($subconflict) and
!defined($subquery) and (scalar(@ARGV) == 0))
{
  print $USAGE;
  exit 1;
}

if (not defined($user) and not defined($object))
{
  $user = $ENV{"USER"};
  (defined($user) and $user ne "") or error("Please pass -user=... or -object=... or set \$USER to a non-empty string");
}

defined($enctrigger) or $enctrigger="[\x00-\x1f]"; #"
$enctrigger eq "none" and $enctrigger="^\x00\$";

if (defined($format))
{
  if ($format ne "a:v" and $format ne "v")
  {
    error("Illegal -format: $format");
  }
}
else
{
  $format="a:v";
}

my $mergeResults = 1; 
if (defined($sort) and not $sort eq "alpha")
{
  if ($sort eq "precedence")
  {
    $mergeResults = 0;
  }
  else
  {
    error("Illegal -sort: $sort");
  }
}

my ($objectClass, $cn);

if (defined($object))
{
  ($objectClass, $cn) = ($object =~ m(^([^/]*)/(.*)));
  if (!defined($objectClass) or !defined($cn))
  {
    error("Illegal -object= parameter");
  }
}

my @attributeSelectionRegexes = @ARGV;
scalar(@attributeSelectionRegexes) == 0 and @attributeSelectionRegexes = ("\@.*");

my ($ldapbase,$ldapuris) = goto_ldap_parse_config();
 # Note: $ldapuris is a reference to an array of URIs
my $ldap = Net::LDAP->new( $ldapuris, timeout => $timeout ) or error("Could not connect to LDAP server!");
my $results = $ldap->bind() ;  # anonymous bind

my @results = ldap_get_object(ldap => $ldap,
                                basedn => $ldapbase,
                                user => $user,
                                timeout => $timeout,
                                filter => $filter,
                                debug => $debug,
                                objectClass => $objectClass,
                                cnou => $cn,
                                subquery => $subquery,
                                sublevel => $sublevel,
                                subconflict => $subconflict,
                                attributeSelectionRegexes => \@attributeSelectionRegexes,
                                enctrigger => $enctrigger,
                                format => $format,
                                dups => 1,  # duplicate removal is done by printEntry()
                                mergeResults => $mergeResults
                );

@results or exit 1;

defined($debug) and print "x:========================== R E S U L T ==========================";

 # print DN if selected by a regex
foreach my $rx (@attributeSelectionRegexes)
{
  my $regex = $rx; # copy so that we don't change the original value
  if (substr($regex, 0, 1) eq "\@") { $regex = substr($regex,1); }
  $regex = "^" . $regex . "\$"; # always match complete string
  if ("dn" =~ m/$regex/) 
  {
    my $dn = $results[0]->dn;
    defined($dn) or $dn = "<undefined>";
    printAttribute("dn", [$dn], $enctrigger, $format);
    last;
  }
}

 # print the other attributes
foreach my $entry (reverse @results)
{
  printEntry($entry, \@attributeSelectionRegexes, $enctrigger, $format, 1);
}

$ldap->unbind();
} #main()

sub error
{
  print STDERR "ERROR: ", @_;
  exit 1
}