February 23, 2010

csvde Command to show disabled accounts

Filed under: Information Technology — Tags: , , , , , , — Tim Lefler @ 4:53 pm

For audit purposes I needed to list all active directory users and prove that ex-employees were either deleted of disabled. There are a couple of techniques to produce the required output. I think the easiest was to make use of the csvde.exe.

Arguements for csvde.exe

CSV Directory Exchange
 
General Parameters
==================
-i              Turn on Import Mode (The default is Export)
-f filename     Input or Output filename
-s servername   The server to bind to (Default to DC of computer's domain)
-v              Turn on Verbose Mode
-c FromDN ToDN  Replace occurences of FromDN to ToDN
-j path         Log File Location
-t port         Port Number (default = 389)
-u              Use Unicode format
-?              Help
 
Export Specific
===============
-d RootDN       The root of the LDAP search (Default to Naming Context)
-r Filter       LDAP search filter (Default to "(objectClass=*)")
-p SearchScope  Search Scope (Base/OneLevel/Subtree)
-l list         List of attributes (comma separated) to look for in an
                LDAP search
-o list         List of attributes (comma separated) to omit from input.
-g              Disable Paged Search.
-m              Enable the SAM logic on export.
-n              Do not export binary values
 
 
Import
======
-k              The import will go on ignoring 'Constraint Violation' and
                'Object Already Exists' errors
 
 
Credentials Establishment
=========================
Note that if no credentials is specified, CSVDE will bind as the currently
logged on user, using SSPI.
 
-a UserDN [Password | *]            Simple authentication
-b UserName Domain [Password | *]   SSPI bind method
 
Example: Simple import of current domain
    csvde -i -f INPUT.CSV
 
Example: Simple export of current domain
    csvde -f OUTPUT.CSV
 
Example: Export of specific domain with credentials
    csvde -m -f OUTPUT.CSV
          -b USERNAME DOMAINNAME *
          -s SERVERNAME
          -d "cn=users,DC=DOMAINNAME,DC=Microsoft,DC=Com"
          -r "(objectClass=user)"
No log files were written.  In order to generate a log file, please
specify the log file path via the -j option.

So to display whether a user is disabled or not we need to extract the “userAccountControl” property.

C:\>Csvde -f UserList.csv -d "dc=domain,dc=com" -r "(ObjectCategory=Person)" -l "displayName, userAccountControl, uSNChanged,whenChanged,whenCreated"
 
Connecting to "(null)"
Logging in as current user using SSPI
Exporting directory to file UserList.csv
Searching for entries...
Writing out entries
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
............................................
Export Completed. Post-processing in progress...
764 entries exported
 
The command has completed successfully

You can translate the userAccountControl number to the account status using the table below.

UserAccountControl_Num Account_Status
512 Account: Enabled
514 Account: ACCOUNTDISABLE
528 Account: Enabled – LOCKOUT
530 Account: ACCOUNTDISABLE – LOCKOUT
544 Account: Enabled – PASSWD_NOTREQD
546 Account: ACCOUNTDISABLE – PASSWD_NOTREQD
560 Account: Enabled – PASSWD_NOTREQD – LOCKOUT
640 Account: Enabled – ENCRYPTED_TEXT_PWD_ALLOWED
2048 Account: INTERDOMAIN_TRUST_ACCOUNT
2080 Account: INTERDOMAIN_TRUST_ACCOUNT – PASSWD_NOTREQD
4096 Account: WORKSTATION_TRUST_ACCOUNT
8192 Account: SERVER_TRUST_ACCOUNT
66048 Account: Enabled – DONT_EXPIRE_PASSWORD
66050 Account: ACCOUNTDISABLE – DONT_EXPIRE_PASSWORD
66064 Account: Enabled – DONT_EXPIRE_PASSWORD – LOCKOUT
66066 Account: ACCOUNTDISABLE – DONT_EXPIRE_PASSWORD – LOCKOUT
66080 Account: Enabled – DONT_EXPIRE_PASSWORD – PASSWD_NOTREQD
66082 Account: ACCOUNTDISABLE – DONT_EXPIRE_PASSWORD – PASSWD_NOTREQD
66176 Account: Enabled – DONT_EXPIRE_PASSWORD – ENCRYPTED_TEXT_PWD_ALLOWED
131584 Account: Enabled – MNS_LOGON_ACCOUNT
131586 Account: ACCOUNTDISABLE – MNS_LOGON_ACCOUNT
131600 Account: Enabled – MNS_LOGON_ACCOUNT – LOCKOUT
197120 Account: Enabled – MNS_LOGON_ACCOUNT – DONT_EXPIRE_PASSWORD
532480 Account: SERVER_TRUST_ACCOUNT – TRUSTED_FOR_DELEGATION (Domain
Controller)
1049088 Account: Enabled – NOT_DELEGATED
1049090 Account: ACCOUNTDISABLE – NOT_DELEGATED
2097664 Account: Enabled – USE_DES_KEY_ONLY
2687488 Account: Enabled – DONT_EXPIRE_PASSWORD – TRUSTED_FOR_DELEGATION -
USE_DES_KEY_ONLY
4194816 Account: Enabled – DONT_REQ_PREAUTH

Another technique is to use a VBScript to query active directory for the accounts. Below is one that I’ve used frequently.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
' Assign Variables

Dim DomainString, fso, DomianObj, UserDel, C, Code
Dim ChkLast, UserObj, Flag, s
 
' Create Object for File System Access

set fso = CreateObject ("Scripting.FileSystemObject")
 
' Set Domain Name
DomainString = "domain.com" 'Modify this line or this script wont work

' Open ADSI and connect to Domain user data

Set DomainObj = GetObject("WinNT://" & DomainString)
DomainObj.Filter = Array("user")
 
' Insure that file does not already exist
IF fso.FileExists ("show_user_account_info.txt") THEN
     set USERDel = fso.GetFile ("show_user_account_info.txt")
     USERDel.Delete
End IF
 
' Create File in temp directory
set C = fso.CreateTextFile ("show_user_account_info.txt", True)
 
on error resume next
' Add collumn headings to new file
C.WriteLine "Name" & vbTab & "FullName" & vbTab & "Description" & _
     vbTab & "LastLogin" & vbTab & "PasswordExpirationDate" & _
     vbTab & "IsAccountLocked" & vbTab & "Class" & vbTab & "UserFlags"
 
' List all users
For Each UserObj In DomainObj
     ChkLast = UserObj.LastLogin ' ChkLast is used to determine the last logon time.
     IF UserObj.UserFlags <> 661103 Then
          s = UserObj.name 
          s = s & vbTab
          s = s & UserObj.FullName 
          s = s & vbTab
          s = s & UserObj.Description
          s = s & vbTab
          s = s & UserObj.LastLogin
          s = s & vbTab
          s = s & UserObj.PasswordExpirationDate
          s = s & vbTab
          s = s & UserObj.IsAccountLocked 
          s = s & vbTab
          s = s & UserObj.Class 
          s = s & vbTab
 
' Convert Flags to more undersandable terms.
               Flag = UserObj.UserFlags
               IF Flag = 66113 THEN
                    Code = "Password never expires and user cannot change password"
               ELSEIF Flag = 8389123 THEN
                    Code = "Disabled"
               ELSEIF     Flag = 577 THEN
                    Code = "Account is not setup right, login not possible"
               ELSEIF Flag = 515 THEN
                    Code = "Account is disabled and user must change password at next logon"
               ELSEIF Flag = 513 THEN
                    Code = "User is active"
               ELSEIF Flag = 66049 THEN
                    Code = "Password Does Not expire"
               ELSE
                    Code = "Unknown Code = " & UserObj.UserFlags
               END IF
 
          s = s & CHR (34) & Code & CHR (34)
          C.WriteLine s ' Write new line to file.
     End IF
Next ' Repeat for all users
Wscript.Quit

No Comments »

No comments yet.

RSS feed for comments on this post. TrackBack URL

Leave a comment

Powered by WordPress