1#!/usr/bin/perl -w 2# Guenther Deschner <gd@samba.org> 3# 4# check for multiple LDAP entries 5 6use strict; 7 8use Net::LDAP; 9use Getopt::Std; 10 11my %opts; 12 13if (!@ARGV) { 14 print "usage: $0 -h host -b base -D admindn -w password [-l]\n"; 15 print "\tperforms checks for multiple sid, uid and gid-entries on your LDAP server\n"; 16 print "\t-l adds additional checks against the local /etc/passwd and /etc/group file\n"; 17 exit 1; 18} 19 20getopts('b:h:D:w:l', \%opts); 21 22my $host = $opts{h} || "localhost"; 23my $suffix = $opts{b} || die "please set base with -b"; 24my $binddn = $opts{D} || die "please set basedn with -D"; 25my $bindpw = $opts{w} || die "please set password with -w"; 26my $check_local_files = $opts{l} || 0; 27 28######################## 29 30 31my ($ldap, $res); 32my (%passwd_h, %group_h); 33my $bad_uids = 0; 34my $bad_gids = 0; 35my $bad_sids = 0; 36my $ret = 0; 37 38if ($check_local_files) { 39 my @uids = `cut -d ':' -f 3 /etc/passwd`; 40 my @gids = `cut -d ':' -f 3 /etc/group`; 41 42 foreach my $uid (@uids) { 43 chomp($uid); 44 $passwd_h{$uid} = $uid; 45 } 46 47 foreach my $gid (@gids) { 48 chomp($gid); 49 $group_h{$gid} = $gid; 50 } 51} 52 53######## 54# bind # 55######## 56 57$ldap = Net::LDAP->new($host, version => '3'); 58 59$res = $ldap->bind( $binddn, password => $bindpw); 60$res->code && die "failed to bind: ", $res->error; 61 62 63 64########################### 65# check for double sids # 66########################### 67 68print "\ntesting for multiple sambaSids\n"; 69 70$res = $ldap->search( 71 base => $suffix, 72 filter => "(objectclass=sambaSamAccount)"); 73 74$res->code && die "failed to search: ", $res->error; 75 76foreach my $entry ($res->all_entries) { 77 78 my $sid = $entry->get_value('sambaSid'); 79 80 my $local_res = $ldap->search( 81 base => $suffix, 82 filter => "(&(objectclass=sambaSamAccount)(sambaSid=$sid))"); 83 84 $local_res->code && die "failed to search: ", $local_res->error; 85 if ($local_res->count > 1) { 86 print "A SambaSamAccount with sambaSid [$sid] must exactly exist once\n"; 87 print "You have ", $local_res->count, " entries:\n"; 88 foreach my $loc_entry ($local_res->all_entries) { 89 printf "\t%s\n", $loc_entry->dn; 90 } 91 ++$bad_sids; 92 } 93} 94 95if ($bad_sids) { 96 $ret = -1; 97 print "You have $bad_sids bad sambaSids in your system. You might need to repair them\n"; 98} else { 99 print "No multiple sambaSids found in your system\n"; 100} 101 102print "-" x 80, "\n"; 103 104########################### 105# check for double groups # 106########################### 107 108print "\ntesting for multiple gidNumbers\n"; 109 110$res = $ldap->search( 111 base => $suffix, 112 filter => "(objectclass=posixGroup)"); 113 114$res->code && die "failed to search: ", $res->error; 115 116foreach my $entry ($res->all_entries) { 117 118 my $gid = $entry->get_value('gidNumber'); 119 my $dn = $entry->dn; 120 121 my $local_res = $ldap->search( 122 base => $suffix, 123 filter => "(&(objectclass=posixGroup)(gidNumber=$gid))"); 124 125 $local_res->code && die "failed to search: ", $local_res->error; 126 if ($local_res->count > 1) { 127 print "A PosixGroup with gidNumber [$gid] must exactly exist once\n"; 128 print "You have ", $local_res->count, " entries:\n"; 129 foreach my $loc_entry ($local_res->all_entries) { 130 printf "\t%s\n", $loc_entry->dn; 131 } 132 ++$bad_gids; 133 next; 134 } 135 136 if ($check_local_files && exists $group_h{$gid}) { 137 print "Warning: There is a group in /etc/group that has gidNumber [$gid] as well\n"; 138 print "This entry may conflict with $dn\n"; 139 ++$bad_gids; 140 } 141} 142 143if ($bad_gids) { 144 $ret = -1; 145 print "You have $bad_gids bad gidNumbers in your system. You might need to repair them\n"; 146} else { 147 print "No multiple gidNumbers found in your system\n"; 148} 149 150print "-" x 80, "\n"; 151 152 153########################### 154# check for double users # 155########################### 156 157print "\ntesting for multiple uidNumbers\n"; 158 159$res = $ldap->search( 160 base => $suffix, 161 filter => "(objectclass=posixAccount)"); 162 163$res->code && die "failed to search: ", $res->error; 164 165 166foreach my $entry ($res->all_entries) { 167 168 my $uid = $entry->get_value('uidNumber'); 169 my $dn = $entry->dn; 170 171 my $local_res = $ldap->search( 172 base => $suffix, 173 filter => "(&(objectclass=posixAccount)(uidNumber=$uid))"); 174 175 $local_res->code && die "failed to search: ", $local_res->error; 176 if ($local_res->count > 1) { 177 print "A PosixAccount with uidNumber [$uid] must exactly exist once\n"; 178 print "You have ", $local_res->count, " entries:\n"; 179 foreach my $loc_entry ($local_res->all_entries) { 180 printf "\t%s\n", $loc_entry->dn; 181 } 182 ++$bad_uids; 183 next; 184 } 185 if ($check_local_files && exists $passwd_h{$uid}) { 186 print "Warning: There is a user in /etc/passwd that has uidNumber [$uid] as well\n"; 187 print "This entry may conflict with $dn\n"; 188 ++$bad_uids; 189 } 190} 191 192if ($bad_uids) { 193 $ret = -1; 194 print "You have $bad_uids bad uidNumbers in your system. You might need to repair them\n"; 195} else { 196 print "No multiple uidNumbers found in your system\n"; 197} 198 199$ldap->unbind; 200 201exit $ret; 202