| 1 | #!/usr/bin/perl -w
|
|---|
| 2 | # Guenther Deschner <[email protected]>
|
|---|
| 3 | #
|
|---|
| 4 | # check for multiple LDAP entries
|
|---|
| 5 |
|
|---|
| 6 | use strict;
|
|---|
| 7 |
|
|---|
| 8 | use Net::LDAP;
|
|---|
| 9 | use Getopt::Std;
|
|---|
| 10 |
|
|---|
| 11 | my %opts;
|
|---|
| 12 |
|
|---|
| 13 | if (!@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 |
|
|---|
| 20 | getopts('b:h:D:w:l', \%opts);
|
|---|
| 21 |
|
|---|
| 22 | my $host = $opts{h} || "localhost";
|
|---|
| 23 | my $suffix = $opts{b} || die "please set base with -b";
|
|---|
| 24 | my $binddn = $opts{D} || die "please set basedn with -D";
|
|---|
| 25 | my $bindpw = $opts{w} || die "please set password with -w";
|
|---|
| 26 | my $check_local_files = $opts{l} || 0;
|
|---|
| 27 |
|
|---|
| 28 | ########################
|
|---|
| 29 |
|
|---|
| 30 |
|
|---|
| 31 | my ($ldap, $res);
|
|---|
| 32 | my (%passwd_h, %group_h);
|
|---|
| 33 | my $bad_uids = 0;
|
|---|
| 34 | my $bad_gids = 0;
|
|---|
| 35 | my $bad_sids = 0;
|
|---|
| 36 | my $ret = 0;
|
|---|
| 37 |
|
|---|
| 38 | if ($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 |
|
|---|
| 68 | print "\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 |
|
|---|
| 76 | foreach 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 |
|
|---|
| 95 | if ($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 |
|
|---|
| 102 | print "-" x 80, "\n";
|
|---|
| 103 |
|
|---|
| 104 | ###########################
|
|---|
| 105 | # check for double groups #
|
|---|
| 106 | ###########################
|
|---|
| 107 |
|
|---|
| 108 | print "\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 |
|
|---|
| 116 | foreach 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 |
|
|---|
| 143 | if ($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 |
|
|---|
| 150 | print "-" x 80, "\n";
|
|---|
| 151 |
|
|---|
| 152 |
|
|---|
| 153 | ###########################
|
|---|
| 154 | # check for double users #
|
|---|
| 155 | ###########################
|
|---|
| 156 |
|
|---|
| 157 | print "\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 |
|
|---|
| 166 | foreach 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 |
|
|---|
| 192 | if ($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 |
|
|---|
| 201 | exit $ret;
|
|---|