Dear Chris,
On 01/12/11 07:12 +0000, Chris Ridd wrote:
On 30 Nov 2011, at 22:21, Nick Urbanik wrote:
Dear Folks,
I am writing Perl software to manage our OpenLDAP cluster using the
slapo.ppolicy overlay to manage password policy. I'm hoping to get
this into production very soon.
My problem: how to efficiently search for users who have expired?
I have seen the code written by Buchan Milne at
http://staff.telkomsa.net/~bgmilne/ldap/, but he is munging with the
operational attributes directly. The code I've written so far has
mostly avoided working with these directly; I've been using
Net::LDAP::Control::PasswordPolicy so far, and am trying to understand
how to construct a suitable filter using this control.
Can anyone point me in the right direction?
The PP control is very much meant for telling a user about *his*
password status. If you combined it with proxy auth, you could
imagine writing something that iterated through every user, and did
some kind of operation (something simple like whoami perhaps)
proxying as that user and requesting PP status back.
That may give you what you want. It may even work! :-)
Well, I have thousands of users, and simply want to create a filter
that will fetch the unexpired users who match various other criteria.
I suspect Buchan's approach is better as it doesn't involve iterating
through each user and the attributes it is using are defined in the
same draft as the PP control, i.e. reasonably standardised.
The problem is that I cannot construct one filter that works for
everyone, because I have multiple policies; I have code like this:
sub _read_ppolicy_times {
my ( $self ) = @_;
my $ldap = _ldapopen $self or return;
my $search = _search $self, $ldap, $POLICY_DN, '(objectclass=pwdPolicy)',
'sub', [ qw( cn pwdMaxAge pwdExpireWarning pwdGraceAuthnLimit ) ]
or return;
if ( $search->code() or $search->count() == 0 ) {
_log_trans_fail $self, $ERR_LDAP_SEARCH_FAIL, 'cannot find ANY ppolicy';
return;
}
my %expires;
foreach my $entry ( $search->entries() ) {
my $pwd_max_age = $entry->get_value( 'pwdMaxAge' ) or next;
$expires{ $entry->get_value( 'cn' ) }
= strftime '%Y%m%d%H%M%SZ', gmtime( time - $pwd_max_age );
}
return \%expires;
}
And then I conduct a search, and loop through the entries removing
those that are expired, like this:
foreach my $entry ( $search->entries() ) {
my $ppolicy = _dns_to_cns $entry->get_value( 'pwdPolicySubentry' );
my $last_changed = $entry->get_value( 'pwdChangedTime' );
if ( exists $expires->{$ppolicy} ) {
next if $no_expired and $expires->{$ppolicy} > $last_changed;
}
else {
$self->log( "Cannot find '$ppolicy' in " . Dumper( $expires ) )
}
push @entries, $entry;
}
This is ugly, especially when I want to have other code to fetch only
users who *have* expired. Do I really need to do this sort of thing?
The server knows which ones have expired; it would be great if I had a
way of asking it to filter them out for me.
--
Nick Urbanik http://nicku.org 808-71011 nick.urba...@optusnet.com.au
GPG: 7FFA CDC7 5A77 0558 DC7A 790A 16DF EC5B BB9D 2C24 ID: BB9D2C24
I disclaim, therefore I am.