Windows Scripting
  Home arrow Windows Scripting arrow Page 3 - Securing Computers and Active Directory
ASP Free Forums 
.NET  
ASP  
ASP Code  
ASP.NET  
ASP.NET Code  
BrainDump  
C#  
Code Examples  
Database  
Database Code  
IIS  
Microsoft Access  
MS SQL Server  
Visual Basic.NET  
Windows Scripting  
Windows Security  
XML  
ASP Web Hosting  
ASP.NET Web Hosting 
Dedicated Servers 
Actuate Whitepapers 
Moblin 
Windows Web Hosting
 
IBM® developerWorks 
Sun Developer Network 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us Get Paid 
Request Media Kit
Contact Us 
Site Map 
Privacy Policy 
Support 
 USERNAME
 
 PASSWORD
 
 
  >>> SIGN UP!  
  Lost Password? 
WINDOWS SCRIPTING

Securing Computers and Active Directory
By: O'Reilly Media
  • Search For More Articles!
  • Disclaimer
  • Author Terms
  • Rating: 5 stars5 stars5 stars5 stars5 stars / 2
    2008-01-24

    Table of Contents:
  • Securing Computers and Active Directory
  • Resetting a Computer Account
  • Finding Inactive or Unused Computers
  • Changing the Maximum Number of Computers a User Can Join to the Domain

  • Rate this Article: Poor Best 
      ADD THIS ARTICLE TO:
      Del.ici.ous Digg
      Blink Simpy
      Google Spurl
      Y! MyWeb Furl
    Email Me Similar Content When Posted
    Add Developer Shed Article Feed To Your Site
    Email Article To Friend
    Print Version Of Article
    PDF Version Of Article
     
     
    ADVERTISEMENT

    Stay one step ahead of the competition. Evaluate and give feedback on some of the hottest web development tools on the market today. Make your opinion heard! Click Here

    Securing Computers and Active Directory - Finding Inactive or Unused Computers


    (Page 3 of 4 )

    Problem

    You want to find inactive computer accounts in a domain.

    Solution

    These solutions might only apply to Windows-based machines. Other types of machines—e.g., Unix, Mac, Network Attached Storage (NAS)—that have accounts in Active Directory might not update their login timestamps or passwords, which are used to determine inactivity.

    Using a command-line interface

    The following query will locate all inactive computers in the current forest:

      > dsquery computer forestroot -inactive <NumWeeks>

    You can also usedomainrootin combination with the
    -doption to query a specific domain:

      > dsquery computer domainroot -d <DomainName> -inactive <NumWeeks>

    or you can target your query at a specific container:

      > dsquery computer ou=MyComputers,dc=rallencorp,dc=com
    -inactive <NumWeeks>

    These commands can only be run against a Windows Server 2003 domain functional level or higher domain.

    You can also use the OldCmp joeware utility to create a report of all computer accounts whose passwords are older than a certain number of days (90 by default) by using the following syntax:

      > oldcmp -report

    To specify an alternate password age witholdcmp, use the–age x switch. You can also use the–lltsswitch to use thelastLogonTimeStampattribute to perform the age calculations. (Without this switch,oldcmpwill usepwdLastSetby default.)

    Using Perl

      #!perl

      #----------------------
      # Script Configuration
      #----------------------
      # Domain and container/OU to check for inactive computer accounts
      my $domain        = 'amer.rallencorp.com';

      # set to empty string to query entire domain
      my $computer_cont = 'cn=Computers,';
      # Number of weeks used to find inactive computers
      my $weeks_ago = 30;
      #----------------------
      # End Configuration
      #----------------------

      use strict;
      use Win32::OLE;
         $Win32::OLE::Warn = 3;
      use Math::BigInt;

      # Must convert the number of seconds since $weeks_ago
      # to a large integer for comparison against lastLogonTimestamp
      my $sixmonth_secs = time - 60*60*24*7*$weeks_ago;
      my $intObj = Math::BigInt->new($sixmonth_secs);
         $intObj = Math::BigInt->new($intObj->bmul('10 000 000'));
      my $sixmonth_int = Math::BigInt->new(
                              $intObj->badd('116 444 736 000 000 000'));
         $sixmonth_int =~ s/^[+-]//;

      # Set up the ADO connections
      my $connObj                         = Win32::OLE->new('ADODB.Connection');
      $connObj->{Provider}                = "ADsDSOObject";
      $connObj->Open;
      my $commObj                         = Win32::OLE->new('ADODB.Command');
      $commObj->{ActiveConnection}        = $connObj;
     
    $commObj->Properties->{'Page Size'} = 1000;

      # Grab the default root domain name
      my $rootDSE = Win32::OLE->GetObject(LDAP://$domain/RootDSE);
      my $rootNC = $rootDSE->Get("defaultNamingContext");

      # Run ADO query and print results
      my $query = "<LDAP://$domain/$computer_cont$rootNC>;";
      $query .= "(&(objectclass=computer)";
      $query .=   "(objectcategory=computer)";
      $query .= "(lastlogontimestamp<=$sixmonth_int));";
      $query .= "cn,distinguishedName;";
      $query .= "subtree";
      $commObj->{CommandText} = $query;
      my $resObj = $commObj->Execute($query);
      die "Could not query $domain: ",$Win32::OLE::LastError,"\n"
       
    unless ref $resObj;

      print "\nComputers that have been inactive for $weeks_ago weeks or more:\n";
      my $total = 0;
      while (!($resObj->EOF)) {
         
    my $cn = $resObj->Fields(0)->value;
          print "\t",$resObj->Fields("distinguishedName")->value,"\n";
          $total++;
          $resObj->MoveNext;
      }
      print "Total: $total\n";

    Discussion

    Using a command-line interface

    The dsquery computer command is very handy for finding inactive computers that have not logged in to the domain for a number of weeks or months. You can pipe the results of the query to the dsrm command-line utility if you want to remove the inactive computer objects from Active Directory in a single command. Here is an example that would delete all computers in the current domain that have been inactive for 12 weeks or longer:

      > for /F "usebackq" %i in (`dsquery computer domainroot -inactive 12`) do dsrm
    %i

    You can also use OldCmp to disable inactive accounts, and then either delete them or move them to an alternate OU. OldCmp has a number of safeties built into the utility to prevent you from deleting a large number of computer accounts without meaning to. For example, OldCmp will not delete an account unless it has first been disabled, it will not modify more than 10 objects at a time unless you manually specify a higher limit, and it simply will not do anything at all to a domain controller computer account under any circumstances. Unless you have a requirement for quickly removing unusedcomputer objects, we’d recommend allowing them to remain inactive for at least three months before removing them. If you don’t really care when the objects get removed, use a year (i.e., 52 weeks) to be on the safe side.

    Using Perl

    With Windows 2000 Active Directory, the only way you can determine if a computer is inactive is to query either the pwdLastSet or lastLogon attributes. The pwdLastSet attribute is a 64-bit integer that translates into the date and time the computer last updated its password. Since computers are supposed to change their password every 30 days, you could run a query that finds the computers that have not changed their password in several months. This is difficult with VBScript because it does not handle 64-bit integer manipulation very well. There are third-party add-ons that provide 64-bit functions, but none of the built-in VBScript functions can do it and it is nontrivial to implement without an add-on.

    ThelastLogonattribute can also be used to find inactive computers because that attribute contains a 64-bit integer representing the last time the computer logged into the domain. The problem with thelastLogonattribute is that it is not replicated. Since it is not replicated, you have to query every domain controller in the domain to find the most recentlastLogonvalue. As you can imagine, this is less than ideal, especially if you have a lot of domain controllers.

    Fortunately, in Windows Server 2003, Microsoft added a new attribute calledlastLogonTimestamptouserandcomputerobjects. This attribute contains the approximate last logon timestamp (again in a 64-bit, large-integer format) for the user or computer and is replicated to all domain controllers. It is the approximate last logon because the domain controllers will update the value only if it hasn’t been updated for a certain period of time (such as a week). This prevents the attribute from being updated constantly and causing a lot of unnecessary replication traffic.

    Since VBScript was out of the question, we turned to our first love—Perl. It is very rare to find a problem that you can’t solve with Perl and this is no exception. The biggest issue is manipulating a number to a 64-bit integer, which we can do with theMath::BigIntmodule.

    First, we determine the time in seconds from 1970 for the date that we want to query computer inactivity against. That is, take the current time and subtract the number of weeks we want to go back. Then we have to convert that number to a big integer. The last step is simply to perform an ADO query for all computers that have alastLogonTimestampless than or equal to the value we just calculated.

    See Also

    Recipe 6.31 for finding users whose accounts are about to expire

    More Windows Scripting Articles
    More By O'Reilly Media


       · This article is an excerpt from the book "Active Directory Cookbook, Second...
     

    Buy this book now. This article is excerpted from chapter eight of the Active Directory Cookbook, Second Edition, written by Robbie Allen and Laura E. Hunter (O'Reilly; ISBN: 059610202X). Check it out today at your favorite bookstore. Buy this book now.

    WINDOWS SCRIPTING ARTICLES

    - Understanding Procedures in VBScript
    - Printing Documents in WSH
    - Generating Outlook Signatures Based on Activ...
    - VBScript: Converting and Formatting with Fun...
    - VBScript: Conversion and Format Functions
    - VBScript: Array Functions
    - VBScript: Strings, You Can`t Function withou...
    - VBScript: More String Functions
    - VBScript: Functioning with Strings
    - Working with the Windows Registry in C++
    - Understanding Objects
    - HTML Applications: Giving WSH a User Interfa...
    - Modifying Computer Objects with Active Direc...
    - Logon Script to Send Email Notifications
    - Securing Computers and Active Directory




    © 2003-2008 by Developer Shed. All rights reserved. DS Cluster 2 hosted by Hostway