#!/usr/bin/perl # # Directory Server Scanner # Program to identify type of Directory Servers on machines remotely. # # Author Nagareshwar Y Talekar (tnagareshwar@gmail.com) # Version 1.3 # # # History # ======= # Ver 1.0 25th Nov 2006 First public release. # Ver 1.1 8th April 2007 Minor modification at command level. # Ver 1.3 23th April 2008 Add Support for IBM Lotus Software & Oracle Directory # Thanks to Nicob (nicob@nicob.net) for adding this support # # # # ################################################################################################## use Net::LDAP; use Net::Ping; use Socket; use Switch; use threads; use strict; $|++; # force auto flush of output buffer my $host; my $isSingleHost = 0; my $disablePing = 0; my $extraTab = ""; # # Usage: perl DirServerScanner.pl [-d] { host | host-range } # #check if any command line parameters specified if( @ARGV < 1 ) { printUsage(); exit; } if( @ARGV == 2 ) { if( $ARGV[0] =~ /-d/i ) { #print "\n Disabling the ping scan...."; $disablePing = 1; } else { printUsage(); exit; } $host = $ARGV[1]; } else { $host = $ARGV[0]; } my @parts = split(/\./, $host); if( @parts != 4 ) { # treat it as single hostname $isSingleHost = 1; $extraTab = "\t" #printUsage(); #print "\n\n Error : Enter proper IP address for the host\n\n"; #exit; } print "\n\n Directory Server Scanner v1.3 \n\t\tby Nagareshwar Y Talekar (tnagareshwar\@gmail.com)\n"; print "\n\n For latest version visit http://www.securityxploded.com\n"; # check if IP range is specified ? our $range1; our $range2; our @range; our $hostCount = 0; if( $host =~ m/-/ ) { @range = split(/-/, $parts[3] ); #print "\n ip range is " . $range[0] . " " . $range[1]; $range1 = $range[0]; $range2 = $range[1]; print "\n\n Scanning for range of host " . $host . "\n"; } else { $isSingleHost = 1; print "\n\n Scanning for host " . $host . "\n" ; } # Now scan for each host one by one print "\n************************************************************"; print "\nHost \t\t ". $extraTab . " Status \t Directory Server "; print "\n************************************************************\n"; if( $isSingleHost ) { scanHost($host, $disablePing); } else { my $baseHost = $parts[0] . "." . $parts[1] . "." . $parts[2]; my @threadList; my $thr; my $i; for ( $i=$range1; $i <= $range2 ; $i++) { my $hostAddress = $baseHost . "." . $i; $hostCount++; $thr = threads->new( \&scanHost, $hostAddress, $disablePing); push(@threadList, $thr); if( $hostCount % 50 == 0 ) { #print "\n\n Waiting for prev threads to terminate..." unless !$verbose; foreach (@threadList) { $_->join(); } @threadList = (); # make the array empty or $#threadList = -1; } } # waiting for all threads to terminate.. foreach (@threadList) { $_->join(); } } print "\n************************************************************"; print "\n\n Finished scanning the hosts\n Cleaning up, please wait...\n\n"; exit; #**************************************************************************** # Scan each host and find out eDir Version sub scanHost { my $target = $_[0]; my $disableCheck = $_[1]; if( !$disableCheck ) { if( !checkHost($target) ) { print "$target \t Dead \t Unknown \n"; return; } } my $ldap = Net::LDAP->new ( $target , timeout => 60, version => 3); if( !$ldap ) { if( !$disableCheck ) { print "$target \t Alive \t Not Present \n"; } else { print "$target \t Unknown \t Unknown \n"; } return; } my $mesg = $ldap->bind ( version => 3 ); if ( $mesg->code ) { #ldap_error_text($mesg->code) print "$target \t Alive \t Present, Unknown\n"; return; } my $result = $ldap->search( base => "", scope => "base", filter => "(objectClass=*)", attrs=> ['vendorversion', 'orcldirectoryversion', 'vendorname', , 'objectClass', 'isGlobalCatalogReady', 'netscapemdsuffix'] ); $ldap->unbind(); my $type = "Unknown"; if( $result ) { my @entries = $result->entries; my @attrs = $entries[0]->attributes(); #print "\n " . $entries[0]->dump; #print "\n total entries found " . @entries; #print "\n total attributes found " . @attrs . "\n"; my $a; my $value; my @values; foreach $a (@attrs) { # print "\n " . $a . " = " . $entries[0]->get_value($a); $value = $entries[0]->get_value($a); if( $a =~ /vendorversion/i ) { if( $value =~ /eDirectory/i ) { $type = "Novell eDirectory"; last; } if( $value =~ /Netscape/i ) { $type = "Netscape Directory"; last; } if( $value =~ /Sun/i ) { $type = "Sun ONE Directory"; last; } next; } if( $a =~ /vendorname/i ) { if( $value =~ /IBM Lotus Software/i ) { $type = "Lotus Domino"; last; } if( $value =~ /Novell/i ) { $type = "Novell eDirectory"; last; } if( $value =~ /Netscape/i ) { $type = "Netscape Directory"; last; } if( $value =~ /Sun Microsystems/i ) { $type = "Sun ONE Directory"; last; } next; } if( $a =~ /orcldirectoryversion/i ) { $type = "Oracle $value"; last; } if( $a =~ /netscapemdsuffix/i ) { $type = "Sun One or Netscape Directory"; last; } # check for active directory if( $a =~ /isGlobalCatalogReady/i ) { $type = "Microsoft Active Directory"; last; } # Check for openldap directory if( $a =~ /objectClass/i ) { @values = $entries[0]->get_value($a); my $v; foreach $v (@values) { if( $v =~ /OpenLDAProotDSE/i ) { $type = "OpenLDAP Directory"; last; } } } } } print "\n"; if( $type =~ /Unknown/i ) { print "$target \t Alive \t Present, Unknown\n"; } else { print "$target \t Alive \t " . $type . "\n"; } #$ldap->unbind(); } #**************************************************************************** # Check if the host is alive sub checkHost { #return 1; my $target = $_[0]; #print "\n Checking for host " . $target; my $p = Net::Ping->new("icmp", 1, 1); my $result = $p->ping($target); $p->close(); return $result; } #**************************************************************************** # print the usage sub printUsage { print "\n\n Directory Server Scanner v1.3 \n\t\tby Nagareshwar Y Talekar (tnagareshwar\@gmail.com)"; print "\n\n For latest version visit http://www.securityxploded.com\n"; print "\n\n Usage: \n\tperl DirServerScanner.pl [-d] { host | host-range } \n\n"; print "\n Options: \n\t-d Do not use ping scan to check if the host is alive \n"; print "\n Example: \n\tperl DirServerScanner.pl -d ldap.myhost.edu\n\tperl DirServerScanner.pl -d 192.168.0.100\n\tperl DirServerScanner.pl 192.168.0.1-100\n\n"; exit; } #****************************************************************************