Upload files to "/"
This commit is contained in:
Binary file not shown.
@@ -0,0 +1,267 @@
|
||||
use Net::LDAP;
|
||||
use Net::Ping;
|
||||
use Date::Calc 'Add_Delta_DHMS';
|
||||
use Getopt::Std;
|
||||
#use POSIX;
|
||||
|
||||
sub usage{
|
||||
print <<EOF;
|
||||
|
||||
"cleanworkstations.exe" will list or delete the older worstation accounts (workstations should connect to a DC once a week so 13 days would be the max time you should be out of contact with a workstation.
|
||||
|
||||
ex: cleanworkstations.exe -d domain -l ou -b base -y days -u username -p password -x -h
|
||||
|
||||
Where:
|
||||
domain: Name of the closest Domain Controller to the machine
|
||||
the script is being run from. This will get a list
|
||||
of all DC's as well as use this machine to authenticate
|
||||
from and delete from if you choose to purge accounts.
|
||||
(Default is dc-00.mathworks.com)
|
||||
*ou: Name of the OU to delete records from. ex... "AH"
|
||||
Only required if no base is defined.
|
||||
(no default defined)
|
||||
*base: Alternate base DN: Defaults to
|
||||
"ou=workstations,ou=$location,dc=ad,dc=mathworks,dc=com"
|
||||
You will get an error if you don't define the base and
|
||||
also don't provide a location OU.
|
||||
*x: Flag to tell program if it should delete all accounts
|
||||
over #days old otherwise it will just list accounts
|
||||
that would have been deleted (Default is 30)
|
||||
*days: Number of days since the machine has been seen that
|
||||
will be up on the report or be deleted (30 day default)
|
||||
!username: The admins netbios username that has rights to delete
|
||||
accounts. (Only used if you are deleting accounts)
|
||||
!password: Coresponding password for the administrator running
|
||||
the script. (Only used if you are deleting accounts)
|
||||
*h: Prints this help file
|
||||
|
||||
All *'s are optional and will be have the correct defaults for each domain
|
||||
if left out.
|
||||
All !'s are optional and are only used if you are going to programatically
|
||||
delete accounts.
|
||||
EOF
|
||||
exit( 1 );
|
||||
|
||||
}
|
||||
|
||||
getopts( 'xhl:d:y:b:u:p:' );
|
||||
my $delete = $Getopt::Std::opt_x;
|
||||
my $location = $Getopt::Std::opt_l;
|
||||
my $domain = ( length( $Getopt::Std::opt_d ) ) ? $Getopt::Std::opt_d : "dc-00.mathworks.com";
|
||||
my $base = ( length( $Getopt::Std::opt_b ) ) ? $Getopt::Std::opt_b : "ou=workstations,ou=$location,dc=ad,dc=mathworks,dc=com";
|
||||
my $days = ( length( $Getopt::Std::opt_y ) ) ? $Getopt::Std::opt_y : 30;
|
||||
my $username = $Getopt::Std::opt_u;
|
||||
my $password = $Getopt::Std::opt_p;
|
||||
my $help = $Getopt::Std::opt_h;
|
||||
|
||||
chomp $domain;
|
||||
chomp $location;
|
||||
$domain = lc($domain);
|
||||
$location = lc($location);
|
||||
if (( $help ) || (((!length($location)) && ($base eq "ou=workstations,ou=$location,dc=ad,dc=mathworks,dc=com") )))
|
||||
#if (( $help ) || (((!length($location)) && ($base = "ou=workstations,ou=,dc=ad,dc=mathworks,dc=com")))
|
||||
{
|
||||
usage();
|
||||
exit( 1 );
|
||||
};
|
||||
|
||||
print "\nDC = $domain\nWorkstation OU = $location\nNumber Days = $days\nDelete? = $delete\n\n";
|
||||
|
||||
# I think this can be 1 hour off due to changes in GMT over daylight savings etc...
|
||||
#$changefromNTepoch = 11644473600; #diference between 1601 and 1970 in seconds
|
||||
$changefromNTepoch = 116444736000000000; #diference between 1601 and 1970 in 100 milliseconds
|
||||
$time = time;
|
||||
$dc= $domain;
|
||||
$~ = OutputFormat;
|
||||
$^ = OutputFormat_Top;
|
||||
$= = 9999;
|
||||
$outfile = "expiredworkstations.$location.txt";
|
||||
|
||||
print "Retrieving list of domain controllers";
|
||||
getDCs();
|
||||
|
||||
print "\nComplete list of domain controllers obtained from $dc:\n";
|
||||
foreach $DC ( sort @DCs ) { print "$DC\n";};
|
||||
|
||||
print "\nQuerying domain controllers (Can take a while - one tick per DC)";
|
||||
foreach $DC ( sort @DCs ) {
|
||||
print ".";
|
||||
if (ping($DC)) {
|
||||
# my $base = "ou=workstations,ou=$location,dc=ad,dc=mathworks,dc=com";
|
||||
my $search = "(&(objectCategory=computer))";
|
||||
|
||||
my $ldap = new Net::LDAP("$DC", port=>389) or die "$@";
|
||||
$ldap->bind(version=>3);
|
||||
my $msg = $ldap->search(
|
||||
base => "$base",
|
||||
filter=>"$search",
|
||||
callback => \&callback);
|
||||
|
||||
die $msg->error if $msg->code;
|
||||
|
||||
sub callback {
|
||||
my ($search, $entry) = @_;
|
||||
$entry = $search->shift_entry;
|
||||
my @results=();
|
||||
if (defined $entry and $entry->get_value("cn") and $entry->get_value("lastLogon")) {
|
||||
$cn = $entry->get_value("cn");
|
||||
$lastlogon = $entry->get_value("lastLogon");
|
||||
push @output, "$cn,$lastlogon,$DC";
|
||||
}
|
||||
}
|
||||
$ldap->unbind;
|
||||
}
|
||||
else { print "\n\nCannot access $dc!!!! Exiting program, will not be accurate unless all dc\'s are accessible.\n\n"; exit }
|
||||
}
|
||||
print "\n\n";
|
||||
|
||||
foreach $line ( sort @output) {
|
||||
my @data = split/,/, $line;
|
||||
my @pdata = split/,/, $pline;
|
||||
|
||||
if (@data[0] eq @pdata[0] && @data[1] > @pdata[1]) {
|
||||
pop @outputdata;
|
||||
push @outputdata, "@data[0],@data[1],@data[2]";
|
||||
}
|
||||
if (@data[0] ne @pdata[0]) {
|
||||
push @outputdata, "@data[0],@data[1],@data[2]";
|
||||
}
|
||||
|
||||
$pline = $line;
|
||||
}
|
||||
|
||||
open (outfile,">$outfile") || die "Can't open output file: $!\n"; # open results to print out
|
||||
|
||||
if ($delete) {
|
||||
|
||||
# bind to DC anon and look up DN of admin running delete option
|
||||
|
||||
$ldap = new Net::LDAP("$domain", port=>389) or die "$@";
|
||||
$ldap->bind( version => 3 );
|
||||
my $search = "(&(cn=$username)(objectClass=user))";
|
||||
my $attrib = "distinguishedName";
|
||||
|
||||
my $result = $ldap->search(base=>"dc=ad,dc=mathworks,dc=com", filter=>"$search",attrs=>"$attrib");
|
||||
die $result->error if $result->code;
|
||||
|
||||
my @entries = $result->entries;
|
||||
foreach $entry (@entries) { @dn = $entry->get(distinguishedName);};
|
||||
$admindn= @dn[0];
|
||||
print "\nAdminDN:$admindn\n";
|
||||
$ldap->unbind;
|
||||
|
||||
# Rebind as admin in order to delete objects
|
||||
|
||||
$ldap = new Net::LDAP("$domain", port=>389) or die "$@";
|
||||
$ldap->bind( version => 3,
|
||||
dn => $admindn,
|
||||
password => $password,
|
||||
);
|
||||
};
|
||||
|
||||
foreach $line ( sort @outputdata) {
|
||||
my @data = split/,/, $line;
|
||||
$netbiosname = @data[0];
|
||||
$lastloggedon = dateconv(@data[1]);
|
||||
$rawdate = @data[1];
|
||||
$logondc = @data[2];
|
||||
$cutofftime = $days*24*60*60;
|
||||
$age = ($time - (($data[1]-$changefromNTepoch)/10000000));
|
||||
if ( $age > $cutofftime )
|
||||
{
|
||||
$kill = "Delete";
|
||||
$fulldn = "cn=$netbiosname,$base";
|
||||
if ($delete)
|
||||
{
|
||||
# delete record from AD
|
||||
$ldap->delete( $fulldn ) or die "$@";
|
||||
}
|
||||
write;
|
||||
write outfile;
|
||||
}
|
||||
else {
|
||||
write;
|
||||
};
|
||||
$kill = "";
|
||||
};
|
||||
|
||||
close (outfile);
|
||||
if ($delete ) {$ldap->unbind;};
|
||||
|
||||
sub ping {
|
||||
my ($host) = @_;
|
||||
my $p = Net::Ping->new("icmp");
|
||||
return 1 if ($p->ping($host, 2));
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub getDCs {
|
||||
my $base = "ou=domain controllers,dc=ad,dc=mathworks,dc=com";
|
||||
my $search = "(&(objectCategory=computer))";
|
||||
|
||||
my $ldap = new Net::LDAP("$dc", port=>389) or die "$@";
|
||||
$ldap->bind(version=>3);
|
||||
my $msg = $ldap->search(
|
||||
base => "$base",
|
||||
filter=>"$search",
|
||||
callback => \&dccallback);
|
||||
|
||||
die $msg->error if $msg->code;
|
||||
|
||||
sub dccallback {
|
||||
my ($search, $entry) = @_;
|
||||
$entry = $search->shift_entry;
|
||||
my @results=();
|
||||
if (defined $entry and $entry->get_value("cn")) {
|
||||
print ".";
|
||||
$cn = $entry->get_value("cn");
|
||||
push @DCs, "$cn";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
sub dateconv {
|
||||
my ($vt_filetime) = @_;
|
||||
|
||||
# Disregard the 100 nanosecond units (rounding might be better)
|
||||
$vt_filetime = substr($vt_filetime, 0, 11);
|
||||
|
||||
my $days = int( $vt_filetime / (24*60*60) );
|
||||
my $hours = int( ($vt_filetime % (24*60*60)) / (60*60) );
|
||||
my $mins = int( ($vt_filetime % (60*60)) / 60 );
|
||||
my $secs = $vt_filetime % 60 ;
|
||||
|
||||
my @date = Add_Delta_DHMS(1601, 1, 1, 0, 0, 0, $days, $hours, $mins, $secs);
|
||||
|
||||
$year = sprintf("%02d", @date[0]);
|
||||
$month = sprintf("%02d", @date[1]);
|
||||
$day = sprintf("%02d", @date[2]);
|
||||
$hour = sprintf("%02d", @date[3]);
|
||||
$minute = sprintf("%02d", @date[4]);
|
||||
$second = sprintf("%02d", @date[5]);
|
||||
|
||||
return "$year-$month-$day $hour:$minute:$second";
|
||||
}
|
||||
|
||||
|
||||
format OutputFormat_Top =
|
||||
Host Name Last Logon Logon DC delete?
|
||||
-----------------------------------------------------------------
|
||||
.
|
||||
|
||||
format OutputFormat =
|
||||
@<<<<<<<<<<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<< ^<<<<<<<< ^<<<<<<<<<<
|
||||
$netbiosname $lastloggedon $logondc $kill
|
||||
.
|
||||
|
||||
format outfile_TOP =
|
||||
Host Name
|
||||
---------------------------------------------------------------------------------------------------------------------
|
||||
.
|
||||
|
||||
format outfile =
|
||||
@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<< ^<<<<<<<< ^<<<<<<<<<<
|
||||
$fulldn $lastloggedon $logondc $kill
|
||||
.
|
||||
|
||||
Reference in New Issue
Block a user