Monday, March 17, 2014

Powershell Function to query Novell LDAP (and likely other non-AD LDAP) and return object(s) with Authentication

It took me awhile to figure out how to do an Authenticated Session with Novell LDAP.  the missing piece, was that our novell LDAP servers were using untrusted certificates.  This little piece of code fixed that issue.  (Probably not the most secure thing to do, but effective)

.SessionOptions.VerifyServerCertificate = { return $true;} 


Original credit goes to: Mike Burr ( http://mikemstech.blogspot.com/ ) for most of the function..
--------------------------------------------------------------------------------------------------

Function GetLDAPObjectwithAuth {

<#

.DESCRIPTION

Sets an LDAP User object attribute to specified Value

.EXAMPLES

SetLDAPObject -LDAPServer "LDAPSERVER Name" -LDAPPort 389 -SSL $false -baseDN "O=BASEDN" -Filter "(uid=smithj01)"

#>

param([string]$LDAPServer,[int]$LDAPPort,[boolean]$SSL,[string]$baseDN, [string]$Filter, [string]$UserName, [securestring]$SecPassWord )

#Load the assemblies

[System.Reflection.Assembly]::LoadWithPartialName("System.DirectoryServices.Protocols") | Out-Null

[System.Reflection.Assembly]::LoadWithPartialName("System.Net") | Out-Null

 

#Connects to LDAP Server using SSL on a non-standard port

$c = New-Object System.DirectoryServices.Protocols.LdapConnection "$($LDAPServer):$($LDAPPort)"



#Set session options

$c.SessionOptions.SecureSocketLayer = $SSL;

$c.SessionOptions.VerifyServerCertificate = { return $true;} #needed for self-signed certificates



# Pick Authentication type:

# Anonymous, Basic, Digest, DPA (Distributed Password Authentication),

# External, Kerberos, Msn, Negotiate, Ntlm, Sicily

$c.AuthType = [System.DirectoryServices.Protocols.AuthType]::Basic



# Gets username and password. Required for Authentication Types requiring Credentials

#$user = Read-Host -Prompt "Username"

#$pass = Read-Host -AsSecureString "Password"

#Creates a credential object to pass to bind to LDAP Connection Object

$NovellCredentials = new-object "System.Net.NetworkCredential" -ArgumentList $UserName,$SecPassWord

# Bind with the network credentials. Depending on the type of server,

# the username will take different forms. Authentication type is controlled

# above with the AuthType

$c.Bind($NovellCredentials);

$scope = [System.DirectoryServices.Protocols.SearchScope]::Subtree

$attrlist = ,"*" #Returns all Attributes

$r = New-Object System.DirectoryServices.Protocols.SearchRequest -ArgumentList `

$baseDN,$Filter,$scope,$attrlist

#$re is a System.DirectoryServices.Protocols.SearchResponse

$re = $c.SendRequest($r);

#How many results do we have?

"A Total of $($re.Entries.Count) Entry(s) found in LDAP Search"

If ($re.Entries.Count -eq 1) #Returns the Only Single Entry

{

Return $Re.Entries[0]

}

elseIf ($re.Entries.Count -eq 0) #Returns Null, No match found on Filter, or problems with LDAP

{

Return $null

}

else # Returns the Entire Collection of Entries

{

#foreach ($i in $re.Entries) { #Do something with each entry here, such as read attributes }

Return $re.Entries

}

}
#End Function
 
#Test example:


$NovellCred = Get-Credential -Message "Enter your Novell Username and Password. Example username: smithj" # Getting the Novell Credential Information

$EDIRLDAPServer = "LDAPSERVER"
$EDIRBaseDN = "O=TEST"
$userID = $NovellCred.UserName.ToUpper()
$TrgtUserID = "smitha"


$PRODLDAPObj = GetLDAPObject -LDAPServer $EDIRLDAPServer -LDAPPort 389 -SSL $false -baseDN $EDIRBaseDN -Filter "(uid=$($userID))"

$userDN = ""
$userDN = (($PRODLDAPObj | select "DistinguishedName" | Out-String).Split() | Select-String -Pattern '^(\w+[=]{1}\w+)([,{1}]\w+[=]{1}\w+)*$').ToString().ToUpper()


$LDAPObj2 = GetLDAPObjectwithAuth -LDAPServer $EDIRLDAPServer -LDAPPort 636 -SSL $true -baseDN $EDIRBaseDN -Filter "(uid=$($TrgtUserID))" -UserName $userDN.toString().ToUpper() -SecPassWord $NovellCred.Password

"Fullname is: $($LDAPObj2.attributes["fullname"].getValues([string]))"

 
$trgtUserDN = (($LDAPObj2 | select "DistinguishedName" | Out-String).Split() | Select-String -Pattern '^(\w+[=]{1}\w+)([,{1}]\w+[=]{1}\w+)*$').ToString().ToUpper()
 
"DN is: $($trgtUserDN)"
 

 

 



Powershell Function to Connect to novell eDirectory LDAP with anonymous auth and return object

Function GetLDAPObject {

<#

.DESCRIPTION

Returns an LDAP object (which contains a collection of attributes), or objects depending on the the search Filter.

Query uses Anonymous Authentication, Function will need to altered for different Credentials, information contained with Commented out Code.

.EXAMPLES

GetLDAPObject -LDAPServer "LDAPSERVER" -LDAPPort 389 -SSL $false -baseDN "o=BASEDN" -Filter "(uid=smithj01)"

#>

param([string]$LDAPServer,[int]$LDAPPort,[boolean]$SSL,[string]$baseDN, [string]$Filter)

#Load the assemblies

[System.Reflection.Assembly]::LoadWithPartialName("System.DirectoryServices.Protocols") | Out-Null

[System.Reflection.Assembly]::LoadWithPartialName("System.Net") | Out-Null

 

#Connects to myopenldap.mikesblog.lan using SSL on a non-standard port

$c = New-Object System.DirectoryServices.Protocols.LdapConnection "$($LDAPServer):$($LDAPPort)"



#Set session options

$c.SessionOptions.SecureSocketLayer = $SSL;



# Pick Authentication type:

# Anonymous, Basic, Digest, DPA (Distributed Password Authentication),

# External, Kerberos, Msn, Negotiate, Ntlm, Sicily

$c.AuthType = [System.DirectoryServices.Protocols.AuthType]::Anonymous



# Gets username and password. Required for Authentication Types requiring Credentials

#$user = Read-Host -Prompt "Username"

#$pass = Read-Host -AsSecureString "Password"

#Creates a credential object to pass to bind to LDAP Connection Object

#$NovellCredentials = new-object "System.Net.NetworkCredential" -ArgumentList $user,$pass

# Bind with the network credentials. Depending on the type of server,

# the username will take different forms. Authentication type is controlled

# above with the AuthType

#$c.Bind($NovellCredentials);

$scope = [System.DirectoryServices.Protocols.SearchScope]::Subtree

$attrlist = ,"*" #Returns all Attributes

$r = New-Object System.DirectoryServices.Protocols.SearchRequest -ArgumentList `

$baseDN,$Filter,$scope,$attrlist

#$re is a System.DirectoryServices.Protocols.SearchResponse

$re = $c.SendRequest($r);

#How many results do we have?

"A Total of $($re.Entries.Count) Entry(s) found in LDAP Search"

If ($re.Entries.Count -eq 1) #Returns the Only Single Entry

{

Return $Re.Entries[0]

}

elseIf ($re.Entries.Count -eq 0) #Returns Null, No match found on Filter, or problems with LDAP

{

Return $null

}

else # Returns the Entire Collection of Entries

{

#foreach ($i in $re.Entries) { #Do something with each entry here, such as read attributes }

Return $re.Entries

}

 

}
#End Function
-----

#Example useage:


$EDIRLDAPServer = "LDAPSERVER"
$EDIRBaseDN = "O=TEST"
$userID = "SMITHJ"


 $LDAPObj = GetLDAPObject -LDAPServer $EDIRLDAPServer -LDAPPort 389 -SSL $false -baseDN $EDIRBaseDN -Filter "(uid=$($userID))"
 
"Fullname is: $($LDAPObj.attributes["fullname"].getValues([string]))"   #sometimes this is 'gecos' attribute not fullname

$strACL = $LDAPObj.Attributes["acl"].GetValues([string]) #sets variable to the ACL attribute returned
 

GroupWise Object API vbscript to archive all GW email in account

'----------------------------------------------------------------------------------------------------------
'GWMailArchive.vbs
'Version 1.2
'Created by: Corey Sines
'Date: 2/19/2014
'Description: Archives all GroupWise Mail Messages to the desired Archive Folder, using the GroupWise
'  Object API
'----------------------------------------------------------------------------------------------------------
'------------Begin Section to Changing to 32bit wscript/cscript if launched on 64bit windows---------------
dim oSH,oFS,strOldWSH
Set oSH = CreateObject("WScript.Shell")
Set oFS = CreateObject("Scripting.FileSystemObject")
If (InStr(WScript.FullName, "cscript")) Then
strOldWSH = oSH.ExpandEnvironmentStrings("%SYSTEMROOT%\SysWOW64\cscript.exe")
Else
strOldWSH = oSH.ExpandEnvironmentStrings("%SYSTEMROOT%\SysWOW64\wscript.exe")
End If
If oFS.FileExists(strOldWSH) Then
    If Not UCase(WScript.FullName) = UCase(strOldWSH) Then
        oSH.Run """" & strOldWSH & """ """ & WScript.ScriptFullName & """", 1, False
        WScript.Quit
    End If
End If
' ------------------------------------------------End Section----------------------------------------------
'----------------------------------------------------------------------------------------------------------
'------------- Begin Section to Check Arguments and set Variables, or Return Proper Usage------------------
dim Args, sGWArchivePath, sGWUserName, sGWPassword
If wscript.arguments.count = 3 then  ' needs all 3 arguments
Set Args = Wscript.Arguments
Else
Wscript.echo "Usage: GWMailArchive.vbs PathtoArchive GWUsername GWPassword"
wscript.quit(1)
End If
' Setting variables to Arguments supplied
sGWArchivePath = Args(0)
sGWUserName = Args(1)
sGWPassword = Args(2)
' ------------------------------------------------End Section----------------------------------------------
'Script starts here...
On Error resume next
 dim wshShell, wshSystemEnv, fso
 dim GWApp, GWAccount, oMsg
 dim iTotalMsgCount, iCount, iPercentComplete
 dim objExplorer

 Set wshShell = CreateObject("WScript.Shell")
 Set wshSystemEnv = wshShell.Environment( "USER" )
 Set GWApp = CreateObject("NovellGroupWareSession") ' instantiating the COM Object for "GW Object API"
 Set GWAccount = GWApp.Login(sGWUserName,SGWPassword) ' Creating and logging into a GroupWise Session
 Set fso = CreateObject ("Scripting.FileSystemObject")
 
 'wscript.echo "GroupWise Archive Path: " & GWAccount.PathToArchive & " : GroupWise FID for User: " & GWAccount.AccountProperty(9) & vbCrLf

 If (IsNull(GWAccount.PathToArchive)) Then ' Checking if no Archive Location was set
 wscript.echo "No Archive Path was set for the user account:" & sGWUserName & ", likely the user never has had an Archive..."
 wshSystemEnv( "TEMPDCP" ) = "NO GROUPWISE ARCHIVE FOUND" 'setting environment variable
 Else
 'Backing up the Old GroupWise Archive Value to an USER Environment Variable "TempVBSValue"
 Wscript.echo "GroupWise Archive Path was set to: " & GWAccount.PathToArchive
 wshSystemEnv( "TEMPDCP" ) = GWAccount.PathToArchive
 End If

 If (InStr(GWAccount.PathToArchive, "C:\")) and NOT(InStr(GWAccount.PathToArchive, "C:\TEMP\ARCHIVER")) Then ' checking if the previous Archive Location was on C:\{Path}
 msgbox "The Previous GroupWise Archive Path was:" & chr(34) & GWAccount.PathToArchive & chr(34) & _
 " which appears to be on the local Workstation. You will need to Archive the Workstation to get any previous GroupWise archive files if there. "
 End If

 wscript.echo "Setting GroupWise ArchivePath to desired location Path: " & sGWArchivePath
  GWAccount.SetArchiveTo(sGWArchivePath)

 iTotalMsgCount = 0 ' variable to hold Total number of messsages to be archived
  wscript.echo "Counting Mail Messages to be Archived, this might take a minute..."
 'Counting the number of messages to be archived, [.]Allmessages property doesn't support the Count Property
 For each oMsg in GWAccount.AllMessages
  'wscript.echo oMsg.ClassName
  If (InStr(oMsg.ClassName,"GW.MESSAGE.MAIL"))  And (oMsg.Deleted <> True) Then
  iTotalMsgCount = iTotalMsgCount + 1
  End If
  Next
 
  wscript.echo "Total Mail Count (Not Deleted, or Archived) is:" & iTotalMsgCount
  iCount = 0
If Not(iTotalMsgCount = 0) Then ' There are actually some messages to Archive
  '------------Begin section to create HTML progress window for Archive % completed----------------------
  iPercentComplete = 0
   Set objExplorer = CreateObject("InternetExplorer.Application") 'instancing COM object to launch IE
 
  'setting up IE properties
  objExplorer.Navigate "about:blank"  
  objExplorer.ToolBar = 0
  objExplorer.StatusBar = 0
  objExplorer.Left = 150
  objExplorer.Top = 200
  objExplorer.Width = 355
  objExplorer.Height = 150
  objExplorer.Visible = 1            
  objExplorer.Document.Body.Style.Cursor = "wait"
  objExplorer.Document.Title = "GroupWise Email Archive progress"
  objExplorer.Document.Body.InnerHTML = "Archive progress: <a id='txtProgress'>0</a> % complete" _
   & "<br/><div style='background-color:blue;width:5px;height:10px;' id='progbar'></div>"
 ' ------------------------------------------------End Section----------------------------------------------
 '----------------------------------------------------------------------------------------------------------
 '-Begin Section to Iterate through each Mail message that isn't Deleted or already Archived and Archive it-
  For each oMsg in GWAccount.AllMessages ' checking each message in allmessages collection
  'Updating the IE Progress Bar
  objExplorer.document.getElementById("txtProgress").innerText=iPercentComplete
  objExplorer.document.getElementById("progbar").style.width=iPercentComplete*3
 
 
  ' Checking if the object is 'Mail', not deleted (trash)
  If (InStr(oMsg.ClassName,"GW.MESSAGE.MAIL"))  And (oMsg.Deleted <> True) Then
   wscript.echo "Message Subject: " & oMsg.Subject
   wscript.echo "Message Type: " & oMsg.ClassName
   wscript.echo "Message ID: " & oMsg.MessageID
   
   If oMsg.Archived = False Then ' Not already Archived
   wscript.echo "Archiving Message..."
   oMsg.Archived = True ' Sending the Message to the Archive
   End If
  
   'wscript.echo "Is the messaged archived?:" & oMsg.Archived
   'wscript.echo "Is the messaged deleted?:" & oMsg.Deleted
   iCount = iCount + 1 ' Counting how many done so far
   iPercentComplete =  Round((iCount * 100) / iTotalMsgCount) ' updating %
  End If
 
  If iCount = iTotalMsgCount Then Exit For 'Needed, without this, Wscript throws an error for some reason
  Next
' ------------------------------------------------End Section----------------------------------------------
'----------------------------------------------------------------------------------------------------------
Else
wscript.echo "There are no GroupWise Messages to archive for user:" & sGWUserName
Dim gwFolders
Set gWFolders = GWAccount.AllFolders
For each Folder in gwFolders
'Folder.name
Next
Wscript.quit(80)  'Exit Code 80 means, no messages available to Archive
End If

' Cleaning up resources and exiting script
 objExplorer.Quit ' closing IE

 set fso = Nothing
 set wshSystemEnv = Nothing
 set wshShell = Nothing
 set objExplorer = Nothing
 set GwApp = Nothing
 set GWAccount = Nothing
 WScript.Sleep 1000
 wscript.quit(0)  ' Exiting with no Error Code, all was successful
 '----------------------------------------------------------------------------------------------------------

GroupWise Admin API vbscript to Disable /Enable User accounts

'------------------------------------------------------------------
'Title:    GroupWise User Account Enable Script
'Purpose:  To Clear Disable Logins checkbox, un-Expire,
'          and Set Visibility to 'system' using the GroupWise API
'Creator:  Corey Sines
'Version:  1.1
'Date:     02/21/2014
'------------------------------------------------------------------
On error resume next
dim GWSystem
dim GWUsers
dim GWUser, TempGWuser
dim Args, sGWDomainPath, sGivenName, sSurName, sMailBoxID
dim iUserCount, bEnabledUser
If wscript.arguments.count = 4 then ' needs all 3 arguments
Set Args = Wscript.Arguments
Else
Wscript.echo "Usage: GWUserEnable.vbs GWDomainPath GivenName Surname GWMailboxID"
wscript.quit(1)
End If
' Setting variables to Arguments supplied
sGWDomainPath = Args(0) ' Needs to a UNC or Mapped Drive Path the current user has read rights to
sGivenName = Args(1)
sSurName = Args(2)
sMailBoxID = Args(3)
Set fso = CreateObject("Scripting.FileSystemObject")
'Checking if GW Domain Path exists and is accessible
If (fso.FolderExists(sGWDomainPath)) Then
set GWSystem=CreateObject("NovellGroupWareAdmin")
GWSystem.Connect( sGWDomainPath ) ' Connecting to the GroupWise System using the UNC / Mapped Path
Else
wscript.echo "GW Domain Path:" & sGWDomainPath & " appears invalid, or the user doesn't have rights to this location."
wscript.quit(97) ' Error Occurred, sending exit code 99
End If
'iterate through the collection of users and output users with login disabled or an expiration date greater than zero and less than today
bEnabledUser = False
GWuser = Null
set GWPostOffices = GWSystem.PostOffices
For Each PO in GWPostOffices
set TempGWUser = PO.FindObject(sMailBoxID)
  If (Ucase(TempGWUser.GivenName) = Ucase(sGivenName)) and (Ucase(TempGWUser.SurName) = Ucase(sSurName)) Then
  wscript.echo sGivenName & " " & sSurName & " Name Matched in GroupWise.."
  set GWUser = PO.FindObject(sMailBoxID)
 End If
Next
If (IsNull(GWUser)) Then
Wscript.echo "No GW Accounts returned in search for User:" & sGivenName & " " & sSurName
set GWUser = Nothing
set GWPostOffices = Nothing
Set GWSystem = Nothing
wscript.quit(99) ' Error Occurred, sending exit code 99
Else
 'Checking if the GW Account is really disabled or expired
 if GWUser.DisableLogin = True _
  or ( GWUser.MailBoxExpDate < now() _
  and  GWUser.MailBoxExpDate > 0 ) then
  wscript.echo "GW User Account Found, current settings are:"
  wscript.echo "GW User Name: " & GWUser.Name & VbCrLf _
  & "GW SurName: " & GWUser.Surname & VbCrLf _
  & "GW Given Name: " &  GWUser.GivenName & VbCrLf _
  & "GW MailboxID: " & GWUser.MailboxID & VbCrLf _
  & "GW Expiration Date " & GWUser.MailBoxExpDate & VbCrLf _
  & "GW Visibility: " & GWUser.Visibility & VbCrLf _
  & "GW Is Logins Disabled?: " & GWUser.DisableLogin

 
  if GWUser.MailboxID = sMailBoxID Then
  wscript.echo "Mailbox ID:" &  sMailBoxID & " matches, Attempting to re-enable the GroupWise Account.."
  GWUser.DisableLogin = False ' Clears the check box for disable logins
  GWUser.MailboxExpDate = CDate("1/1/1899 1:00:00 AM") 'This date clears the Expiration
  GWUser.Visibility = 2  ' 2 is System Visibility

  'Commit the Changes
  GWUser.Commit()
  GWSystem.Commit()
 
  wscript.sleep 2000
   If GWUser.DisableLogin = False then
   Wscript.echo "Success!!"
   bEnabledUser = True
   Else
   wscript.echo "Failed!!"
   End If
 
  End if
 Else
 wscript.echo "GW Account:" & sGivenName & " " & sSurName & " was not disabled, so no work to do..."
 set GWUser = Nothing
 set GWPostOffices = Nothing
 Set GWSystem = Nothing
 wscript.quit(98) ' Error Occurred, sending exit code 98
 End If
End If
If bEnabledUser = False Then
wscript.echo "Unknown Error..GW Account:" & sGivenName & " " & sSurName & "  Was not successfully enabled..."
set GWUser = Nothing
set GWPostOffices = Nothing
Set GWSystem = Nothing
wscript.quit(96) ' Error Occurred, sending exit code 96
End If
set GWUser = Nothing
set GWPostOffices = Nothing
Set GWSystem = Nothing

##########################################################################
'------------------------------------------------------------------
'Title:    GroupWise User Account Disable Script
'Purpose:  To Disable Logins, Expire, and Set Visibility to 'none'
'          using the GroupWise API
'Creator:  Corey Sines
'Version:  1.1
'Date:     02/21/2014
'------------------------------------------------------------------
On error resume next
dim GWSystem
dim GWUsers
dim GWUser
dim Args, sGWDomainPath, sGivenName, sSurName
dim iUserCount, bUserDisabled
dim fso
If wscript.arguments.count = 4 then  ' needs all 3 arguments
Set Args = Wscript.Arguments
Else
Wscript.echo "Usage: GWUserDisable.vbs GWDomainPath GivenName Surname MailboxID"
wscript.quit(1)
End If
' Setting variables to Arguments supplied
sGWDomainPath = Args(0) ' Needs to a UNC or Mapped Drive Path the current user has read rights to
sGivenName = Args(1)
sSurName = Args(2)
sMailBoxID = Args(3)
Set fso = CreateObject("Scripting.FileSystemObject")
'Checking if GW Domain Path exists and is accessible
If (fso.FolderExists(sGWDomainPath)) Then
set GWSystem=CreateObject("NovellGroupWareAdmin")
GWSystem.Connect( sGWDomainPath ) ' Connecting to the GroupWise System using the UNC / Mapped Path
Else
wscript.echo "GW Domain Path:" & sGWDomainPath & " appears invalid, or the user doesn't have rights to this location."
wscript.quit(97) ' Error Occurred, sending exit code 99
End If
'iterate through the collection of users and output users with login disabled or an expiration date greater than zero and less than today
bUserDisabled = False
GWuser = Null
set GWPostOffices = GWSystem.PostOffices
For Each PO in GWPostOffices
set TempGWUser = PO.FindObject(sMailBoxID)
  If (Ucase(TempGWUser.GivenName) = Ucase(sGivenName)) and (Ucase(TempGWUser.SurName) = Ucase(sSurName)) Then
  wscript.echo sGivenName & " " & sSurName & " Name Matched in GroupWise.."
  set GWUser = TempGWUser
 End If
Next
If (IsNull(GWUser)) Then
wscript.echo "No GW Accounts returned in search for User:" & sGivenName & " " & sSurName
set GWUser = Nothing
set GWPostOffices = Nothing
Set GWSystem = Nothing
wscript.quit(99) ' Error Occurred, sending exit code 99
Else
  if GWUser.DisableLogin = False  _
   or ( GWUser.MailBoxExpDate > now() _
   and  GWUser.MailBoxExpDate <= 0 ) then ' Checking if User account is disabled or expired
    wscript.echo "GW User Account Found, current settings are:"
    wscript.echo "GW User Name: " & GWUser.Name & VbCrLf _
     & "GW SurName: " & GWUser.Surname & VbCrLf _
     & "GW Given Name: " &  GWUser.GivenName & VbCrLf _
     & "GW MailboxID: " & GWUser.MailboxID & VbCrLf _
     & "GW Expiration Date " & GWUser.MailBoxExpDate & VbCrLf _
     & "GW Visibility: " & GWUser.Visibility & VbCrLf _
     & "GW Is Logins Disabled?: " & GWUser.DisableLogin

 
   if GWUser.MailboxID = sMailBoxID Then
   wscript.echo "Mailbox ID:" &  sMailBoxID & " matches, attempting to disable logins and expire the GroupWise Account.."
   GWUser.DisableLogin = True
   GWUser.MailboxExpDate = CDate(Now()) 'Disabling the account as of now
   GWUser.Visibility = 4 ' 4 equals a visibility of 'none'
 
   'Commit the Changes
   GWUser.Commit()
   GWSystem.Commit()
   
   wscript.sleep 2000
    If GWUser.DisableLogin = True then
    wscript.echo "Success!!"
    bUserDisabled = True
    '   wscript.echo "After Changes, here is the user info.."
    '   wscript.echo "GW User Name: " & GWUser.Name & VbCrLf _
    '   & "GW SurName: " & GWUser.Surname & VbCrLf _
    '   & "GW Given Name: " &  GWUser.GivenName & VbCrLf _
    '   & "GW MailboxID: " & GWUser.MailboxID & VbCrLf _
    '   & "GW Expiration Date " & GWUser.MailBoxExpDate & VbCrLf _
    '   & "GW Visibility: " & GWUser.Visibility & VbCrLf _
    '   & "GW Is Logins Disabled?: " & GWUser.DisableLogin
    End If
   End If
  Else
   wscript.echo "GW Account:" & sGivenName & " " & sSurName & " was not enabled, so no work to do..."
    set GWUser = Nothing
   set GWPostOffices = Nothing
   Set GWSystem = Nothing
   wscript.quit(98) ' Error Occurred, sending exit code 98
  End if
End If
If bUserDisabled = False Then
 wscript.echo "Unknown Error..GW Account:" & sGivenName & " " & sSurName & "  Was not successfully disabled..."
 set GWUser = Nothing
 set GWPostOffices = Nothing
 Set GWSystem = Nothing
 wscript.quit(96) ' Error Occurred, sending exit code 96
End If