# Compares directories on the servers against who is using them in user manager # If no one claims the directory as a home directory in user manager, it is # dubbed an orphan and printed to orphans.txt. An e-mail is sent to when the script # is complete. This will Get NT4 accounts, or Active Directory (AD) Accounts. # # Required: File conatining a list of all servers with user shares (1 server / line) # Modify Variables: $domain, $serverin, $in, $out, $logfile, $smtp, $ADSPath # # Optional: An SMTP server with open relay (only to use mail capability) # # Authored by Jonathan E. Dyer use strict; use Win32::OLE 'in'; use Win32::NetAdmin qw(GetUsers UserGetAttributes GetDomainController); my $out="//mfappjp1/c\$/scripts/Orphan/accounts.tmp"; open OUT,">$out" or die "Can't open $out for write"; &get_NT4_accts(); &get_AD_accts(); close OUT; &compare(); &SendEmail(); sub get_NT4_accts{ my $filter='FILTER_NORMAL_ACCOUNT'; my $domain='XXXXXXXX'; my ($x,$homeDir,$account,$PDC,@accounts); # Find an NT4 Domain Controller GetDomainController("", $domain, $PDC); # Get the Accounts from the Domain GetUsers($PDC,$filter, \@accounts) or die "Can't get users $!"; @accounts = grep (!/\$$/,@accounts); #filter doesn't seem to work, so need to weed out machines. print "got $domain accounts\n"; # Go back and get the HomeDirectory for each account foreach $account(@accounts){ UserGetAttributes("$PDC",$account,$x,$x,$x,$homeDir,$x,$x,$x) or warn "UserGetAttributes() failed: $^E"; $homeDir=lc ($homeDir); $account=lc ($account); print OUT "$account\t$homeDir\n"; } print "wrote $domain accounts\n"; sleep 15; } sub get_AD_accts{ # get ADO object, set the provider, open the connection my $ADO = Win32::OLE->new("ADODB.Connection"); $ADO->{Provider} = "ADsDSOObject"; $ADO->Open("ADSI Provider"); # Create the ADO Command my $ADSPath = "LDAP://OU=group,DC=subdomain,DC=domain,DC=com"; my $ADOCmd=Win32::OLE->new("ADODB.Command"); $ADOCmd->{ActiveConnection}=$ADO; $ADOCmd->{CommandText}="<$ADSPath>;(objectClass=User);samAccountName,HomeDirectory;SubTree";#new # Next line VERY IMPORTANT if the domain has more than 1000 accounts. $ADOCmd->Properties->{"Page Size"}=10000; #Execute the Command my $users=$ADOCmd->Execute; #Extract the Info (AccountName, HomeDirectory) from the returned object until ($users->EOF){ my $homeDir=lc($users->Fields(1)->{Value}); my $account=lc($users->Fields(0)->{Value}); print OUT "$account\t$homeDir\n"; $users->MoveNext; } $users->Close; $ADO->Close; print "Wrote CORP Accounts\n"; } sub ole_error_check{ if (Win32::OLE->LastError( )){ die Win32::OLE->LastError(); } } sub compare{ my (%is_acct,$x,$key,$homeDir,$account,$userDir,$server); my $in="//XXXXXX/XXXXX/XXXXX/accounts.tmp"; my $out="//XXXXXX/XXXXX/XXXXX/orphans.tmp"; my $serverin="//XXXXXX/XXXXX/XXXXX/fileprint.txt"; print "Starting Comparison\n"; %is_acct=(); open (IN,"<$in") or die "Can't open $in for read"; open (SERVERS,"<$serverin") or die "Can't open Server file for read"; open (OUT,">$out") or die "Can't open $in for write"; # Create a hash with user accounts and home directory paths while (){ chomp; s/\\/\//g; ($account, $homeDir) = split /\t/; $homeDir = lc ($homeDir); $is_acct{$homeDir}=$account; #may be a problem } print "Hash complete\n"; # Check for user shares on D$ and E$ and exit if not there... foreach $server (){ chomp $server; my $dir1="//$server/d\$/users"; if (!(-e "$dir1")){#if directory doesn't exist try d$ $dir1="//$server/e\$/users"; if (!(-e "$dir1")){#if directory doesn't exist try d$ $dir1="//$server/users"; if (!(-e "$dir1")){ next; } } } # Read in the user shares from the servers opendir(DIR, $dir1) or die "can't opendir $dir1: $!"; my @dirs = grep { !/^\./ && -d "$dir1/$_" } readdir(DIR) or warn "can't grep"; #weed out dots and get only dirs closedir DIR; @dirs = map (lc "//$server/$_", @dirs); print "read directories from $server\n"; foreach $userDir (@dirs){ print OUT "$userDir"; if(!exists $is_acct{$userDir}){ print OUT ": Orphan"; } print OUT "\n"; } } close OUT; } sub SendEmail { my $logfile="//XXXXXX/XXXXX/XXXXX/orphans.txt"; if (-e $logfile){ use Net::SMTP; my $from="$ENV{USERNAME}"; my $smtp = Net::SMTP->new('SMTPRelay'); $smtp->mail($from); $smtp->to('you@here.com','me@here.com'); $smtp->data(); $smtp->datasend("Subject: Orphan Script Complete\n"); $smtp->datasend("\n"); $smtp->datasend("This message was generated and sent by Perl script without major human intervention. The Orphans listed are a guideline, and apply only to the XXXXX and XXXXX domains. \n\nfile://XXXXXXX/XXXXX/XXXXXX/XXXXXX/orphans.txt\n"); $smtp->dataend(); }else{ die "something went wrong! in mail send"; } }