package OneUnified::isADGroupMember; # Created 2007/03/08 # Copyright 2007 One Unified # Updated 2007/03/27: Added default return 0 for CheckMembership # Updated 2007/03/30: Fixed initialization of $base require Exporter; @ISA = qw(Exporter); @EXPORT = qw(isMember); use strict; use Net::LDAP; use OneUnified::Const; # need to validate user is still active # use 'apt-get install libnet-ldap-perl' for dependencies #my $base = 'DC=example,DC=net'; # directory search base #my $binduser = 'servicacct@example.net'; # service account userid for ad binding #my $bindpwd = 'password'; # password for ad binding #my $bindaddress = 'ad.example.net'; # bind address go global catalog server my ( $base, $bindaddress, $binduser, $bindpwd ); sub isMember($$) { my ( $user, $group ) = @_; ( $base, $bindaddress, $binduser, $bindpwd ) = getADParams(); # # Connect and bind # my $ad = Net::LDAP->new($bindaddress) or die "Could not connect!"; my $mesg = $ad->bind($binduser, password=>$bindpwd, version => 3 ); # print( 'Bind Name: ' . $mesg->error_name() . "\n" ); # print( 'Bind Message: ' . $mesg->error_text() . "" ); # print( 'Bind Error: ' . $mesg->error() . "\n" ); # print( 'Bind DN: ' . $mesg->dn() . "\n" ); # print( 'Bind isError: ' . $mesg->is_error() . "\n" ); # # perform lookup # my $return = CheckMembership( $ad, $user, $group ); # # finish up and return # $mesg = $ad->unbind; return $return; } sub CheckMembership($$$) { my ( $ad, $targetuser, $targetgroup ) = @_; my ( $filter, $attrs ); my ( $mesg, $count ); my %examinedgroups; # groups that have been examined for contained group members my @newgroups; # groups that need to be examined for contained group members # will use a loop to keep processing new groups until all groups have been examined # this provides a list of examined groups # the list of examined groups is evaluated to see if the user is a member of any of them my ( $userentry, $groupentry ); my ( $userdn, $groupdn ); # obtain distinguishedName for targetuser $attrs = ['distinguishedName','memberOf']; $filter = "&(samaccountname=$targetuser)(objectClass=user)"; $mesg = $ad->search( base => $base, filter => $filter, attrs => $attrs ); if ( 1 != $mesg->count ) { # didn't find a single user return 0; } $userentry = $mesg->entry( 0 ); $userdn = $userentry->dn(); # obtain distinguishedName targetgroup $filter = "&(samaccountname=$targetgroup)(objectClass=group)"; $attrs = ['distinguishedName']; $mesg = $ad->search( base => $base, filter => $filter, attrs => $attrs ); if ( 1 != $mesg->count ) { # didn't find a single group return 0; } $groupentry = $mesg->entry(0); $groupdn = $groupentry->dn(); # # start to evaluate user membership of groups # if ( $userentry->exists( 'memberOf' ) ) { foreach my $val ( $userentry->get_value( 'memberOf' ) ) { push( @newgroups, $val ); } } $attrs = ['memberOf']; my ( $dn, $entry ); while ( $dn = pop( @newgroups ) ) { if ( $dn eq $groupdn ) { return 1; } $examinedgroups{$dn} = 1; # assign to examined groups # retrieve members $filter = "&(distinguishedName=$dn)(objectClass=group)"; $mesg = $ad->search( base => $base, filter => $filter, attrs => $attrs ); $count = $mesg->count; if ( 1 == $count ) { $entry = $mesg->entry( 0 ); if ( $entry->exists( 'memberOf' ) ) { foreach my $val ( $entry->get_value( 'memberOf' ) ) { if ( !defined( $examinedgroups{ $val } ) ) { push( @newgroups, $val ); } } } } } return 0; } 1;