61
62
bind DN and password should be reserved for the occasional case where you
62
63
wish to update the debconf configuration data.
67
Enable access to individual LDAP entries, instead of fetching them
68
all at once in the beginning. This is very useful if you want to monitor your
69
LDAP logs for specific debconf keys requested. In this way, you could also
70
write custom handling code on the LDAP server part.
72
Note that when this option is enabled, the connection to the LDAP server
73
is kept active during the whole Debconf run. This is a little different
74
from the all-in-one behavior where two brief connections are made to LDAP;
75
in the beginning to retrieve all the entries, and in the end to save
68
use fields qw(server port basedn binddn bindpasswd exists);
82
use fields qw(server port basedn binddn bindpasswd exists keybykey ds);
90
104
debug "db $this->{name}" => "talking to $this->{server}, data under $this->{basedn}";
92
106
# Whee, LDAP away! Net::LDAP tells us about all these methods.
93
my $ds = Net::LDAP->new($this->{server}, port => $this->{port}, version => 3);
107
$this->{ds} = Net::LDAP->new($this->{server}, port => $this->{port}, version => 3);
95
109
$this->error("Unable to connect to LDAP server");
96
110
return; # if not fatal, give up anyway
101
115
if (!($this->{binddn} && $this->{bindpasswd})) {
102
116
debug "db $this->{name}" => "binding anonymously; hope that's OK";
117
$rv = $this->{ds}->bind;
105
119
debug "db $this->{name}" => "binding as $this->{binddn}";
106
$rv = $ds->bind($this->{binddn}, password => $this->{bindpasswd});
120
$rv = $this->{ds}->bind($this->{binddn}, password => $this->{bindpasswd});
109
123
$this->error("Bind Failed: ".$rv->error);
117
131
On initialization, connect to the directory, read all of the debconf data
118
132
into the cache, and close off the connection again.
134
If KeyByKey is enabled, then skip the complete data load and only retrieve
135
few keys required by debconf.
123
140
my $this = shift;
125
142
$this->SUPER::init(@_);
127
debug "db $this->{name}" => "getting database data";
128
my $ds=$this->binddb;
130
my $data = $ds->search(base => $this->{basedn}, sizelimit => 0, timelimit => 0, filter => "(objectclass=debconfDbEntry)");
132
$this->error("Search failed: ".$data->error);
135
# Every language does LDAP search() returns fairly similarly. Perl's
136
# modus is documented in Net::LDAP::Search, for those interested.
137
my $records = $data->as_struct();
138
debug "db $this->{name}" => "Read ".$data->count()." entries";
145
return unless $this->{ds};
140
147
# A record of all the existing entries in the DB so we know which
141
148
# ones need to added, and which modified
142
149
$this->{exists} = {};
144
# This is a rather great honking loop, but it's quite simply a nested
145
# bunch of loops iterating through every DN, attribute, and value in
146
# the returned set (the complete debconf database) and storing it in
147
# a format which the cache driver hopefully understands.
148
foreach my $dn (keys %{$records}) {
149
my $entry = $records->{$dn};
150
debug "db $this->{name}" => "Reading data from $dn";
151
my %ret = (owners => {},
158
foreach my $attr (keys %{$entry}) {
159
if ($attr eq 'objectclass') {
162
debug "db $this->{name}" => "Setting data for $attr";
163
my $values = $entry->{$attr};
164
foreach my $val (@{$values}) {
165
debug "db $this->{name}" => "$attr = $val";
166
if ($attr eq 'owners') {
167
$ret{owners}->{$val}=1;
168
} elsif ($attr eq 'flags') {
169
$ret{flags}->{$val}='true';
170
} elsif ($attr eq 'cn') {
172
} elsif ($attr eq 'variables') {
173
my ($var, $value)=split(/\s*=\s*/, $val, 2);
174
$ret{variables}->{$var}=$value;
177
$ret{fields}->{$attr}=$val;
151
if ($this->{keybykey}) {
152
debug "db $this->{name}" => "will get database data key by key";
155
debug "db $this->{name}" => "getting database data";
156
my $data = $this->{ds}->search(base => $this->{basedn}, sizelimit => 0, timelimit => 0, filter => "(objectclass=debconfDbEntry)");
158
$this->error("Search failed: ".$data->error);
182
$this->{cache}->{$name} = \%ret;
183
$this->{exists}->{$name} = 1;
161
my $records = $data->as_struct();
162
debug "db $this->{name}" => "Read ".$data->count()." entries";
164
parse_records($records);
186
# Having done all of that, all that remains is to clean up.
258
240
if ($this->{exists}->{$item}) {
259
$rv = $ds->modify($entry_dn, replace => \%modify_data);
241
$rv = $this->{ds}->modify($entry_dn, replace => \%modify_data);
261
$rv = $ds->add($entry_dn, attrs => $add_data);
243
$rv = $this->{ds}->add($entry_dn, attrs => $add_data);
264
246
$this->error("Modify failed: ".$rv->error);
250
$this->{ds}->unbind();
270
252
$this->SUPER::shutdown(@_);
257
Empty routine for all-in-one db fetch, but does some actual
258
work for individual keys retrieval.
264
return unless $this->{keybykey};
265
my $entry_cn = shift;
267
my $records = $this->get_key($entry_cn);
268
return unless $records;
270
debug "db $this->{name}" => "Read entry for $entry_cn";
272
$this->parse_records($records);
279
277
Called by Cache::shutdown, nothing to do because already done in LDAP::shutdown
297
Retrieve individual key from LDAP db.
298
The function is a no-op if KeyByKey is disabled.
299
Returns entry->as_struct if found, undef otherwise.
305
return unless $this->{keybykey};
306
my $entry_cn = shift;
308
my $data = $this->{ds}->search(
309
base => $this->{basedn},
312
filter => "(&(cn=$entry_cn)(objectclass=debconfDbEntry))");
315
$this->error("Search failed: ".$data->error);
318
return unless $data->entries;
322
# Parse struct data (such as one returned by get_key())
323
# into internal hash/cache representation
328
# This is a rather great honking loop, but it's quite simply a nested
329
# bunch of loops iterating through every DN, attribute, and value in
330
# the returned set (the complete debconf database) and storing it in
331
# a format which the cache driver hopefully understands.
332
foreach my $dn (keys %{$records}) {
333
my $entry = $records->{$dn};
334
debug "db $this->{name}" => "Reading data from $dn";
335
my %ret = (owners => {},
342
foreach my $attr (keys %{$entry}) {
343
if ($attr eq 'objectclass') {
346
debug "db $this->{name}" => "Setting data for $attr";
347
my $values = $entry->{$attr};
348
foreach my $val (@{$values}) {
349
debug "db $this->{name}" => "$attr = $val";
350
if ($attr eq 'owners') {
351
$ret{owners}->{$val}=1;
352
} elsif ($attr eq 'flags') {
353
$ret{flags}->{$val}='true';
354
} elsif ($attr eq 'cn') {
356
} elsif ($attr eq 'variables') {
357
my ($var, $value)=split(/\s*=\s*/, $val, 2);
358
$ret{variables}->{$var}=$value;
361
$ret{fields}->{$attr}=$val;
366
$this->{cache}->{$name} = \%ret;
367
$this->{exists}->{$name} = 1;
299
373
Matthew Palmer <mpalmer@ieee.org>
375
Davor Ocelic <debconf@spinlocksolutions.com> -
376
Added KeyByKey support for http://infrastructures.spinlocksolutions.com/