Wednesday, December 16, 2015

Tis the season for vacation clearing (and password expiration)

As we approach the end of the year, along with its holidays, its common for many employees to take leave for long periods of time.  So as a gift to helpdesks everywhere, often they would request to know who will have their password expire during the peak holiday times (to prepare for the support calls).  To build a list like this is quite easy with powershell.  This assumes you don't have fine grain password policies.  In this example, we look at expiring passwords between Dec 21 and Jan 4 given the working days and anticipated return dates around the Christmas and New Years holidays:

import-module activedirectory

#grab the domain wide password policy and extract a # of days integer
$passwordage = (Get-ADDefaultDomainPasswordPolicy).MaxPasswordAge |select -exp days

#define your start and end filter dates and subtract the max Password age value.
#We need to calculate using passwordlastset timestamps

$startdate = ([datetime]"12-21-2015").adddays(-$passwordage)
$enddate = ([datetime]"1-4-2016").adddays(-$passwordage)

#Filter as much as possible on the LDAP side with the date ranges.
#The Select statement includes a calculated
#expression to convert the passwordlastset value to an actual expiration date.
#Convert to CSV and output to file.
#Zip it and mail it out.

get-aduser -filter {(enabled -eq $true) -and (passwordlastset -ge $startdate) -and (passwordlastset -le $enddate)} -Properties passwordlastset, mail | select samaccountname, name, mail, @{name="ExpirationDate"; exp={$_.passwordlastset.adddays($passwordage)}} | convertto-csv -notypeinfo | out-file .\expiringholidays.csv

Tuesday, December 15, 2015

Checking Mcafee DAT version information remotely with powershell

This script can be used to remotely check a Mcafee client's datversion number and the date of the DAT file's release. It uses basic remote registry reading techniques, so remote registry access (usually administrator on the remote machine) will be required for it to work. You can use this script as a template for other registry reading operations that you may need. It is a basic script that only accepts single computer input. You can change parameters and turn this into a function to handle pipeline or array input.

Update July 2018. Added a secondary registry key in due to some differences I'm seeing in my environment lately. With different product versions and EPO use, this location may move around a bit. If you find this code doesn't work for you, check the current dat version in the taskbar icon, then search the registry for the dat version number. This should get you to the location that your product is storing this information in.


param (
 [parameter(mandatory=$true)][string]$computername
)
function ping-host([string]$computername) {
 #This function will perform a simple, small size single packet ping of a machine and return true/false for the result
  if ([string]::IsNullOrEmpty($computername) ) {return $false}
  #ping first for reachability check
  $po = New-Object net.NetworkInformation.PingOptions
  $po.set_ttl(64)
  $po.set_dontfragment($true)
  [Byte[]] $pingbytes = (65,72,79,89)
  $ping = new-object Net.NetworkInformation.Ping
  $savedEA = $Erroractionpreference
  $ErrorActionPreference = "silentlycontinue"
  $pingres = $ping.send($computername, 1000, $pingbytes, $po)
  if (-not $?) {return $false}
  $ErrorActionPreference = $savedEA
  if ($pingres.status -eq "Success") { return $true } else {return $false}
}


if ((ping-host $computername) -eq $false) {
 New-Object PSobject -Property @{
  Computername = $computername
  DATVersion = "System Not Online"
  Datdate = $null
 }
} else {

 try {
  #Set up the key that needs to be accessed and what registry tree it is under
  $key = "Software\McAfee\AVEngine"
  $type = [Microsoft.Win32.RegistryHive]::LocalMachine

  #open up the registry on the remote machine and read out the TOE related registry values
  $regkey = [Microsoft.win32.registrykey]::OpenRemoteBaseKey($type,$computername)
  $regkey = $regkey.opensubkey($key)
  $status = $regkey.getvalue("AVDatVersion")
  $datdate = $regkey.getvalue("AVDatDate")
 } catch {
  try {
   $key = "Software\Wow6432Node\McAfee\AVEngine"
   $type = [Microsoft.Win32.RegistryHive]::LocalMachine
   #open up the registry on the remote machine and read out the TOE related registry values
   $regkey = [Microsoft.win32.registrykey]::OpenRemoteBaseKey($type,$computername)
   $regkey = $regkey.opensubkey($key)
   $status = $regkey.getvalue("AVDatVersion")
   $datdate = $regkey.getvalue("AVDatDate")
  } catch {
     #try newer registry location
    try {
     $key = "Software\Wow5432Node\Network Associates\ePolicy Orchestrator\Application Plugins\VIRUSCAN880"
     $regkey = [Microsoft.win32.registrykey]::OpenRemoteBaseKey($type,$computername)
     $regkey = $regkey.opensubkey($key)
     $status = $regkey.getvalue("DATVersion")
     $datdate = $regkey.getvalue("DatDate")
    } catch {
      $status = "Cannot read regkey"
    }
  }
 }
 New-Object PSobject -Property @{
  Computername = $computername
  DATVersion = $status
  DatDate = $datdate
 } |select Computername,DatVersion,DatDate
}

Thursday, December 3, 2015

Powershell Switch for a numeric range

There are several ways of handling a range of values in a Switch statement in powershell. In this example, I will show a simple conversion of a numeric month value to a quarter [string].

First example:
switch($month){
 {1..3 -contains $_}{"Q1"}
 {4..6 -contains $_}{"Q2"}
 {7..9 -contains $_}{"Q3"}
 {10..12 -contains $_}{"Q4"}
 
}


The range operator returns an array of the numbers in that specified range, so we use -contains to test our value. If we left out -contains, all switch values would match as no comparison is being made, yet the range is being evaluated as true.

Second example:
switch($month) {
 {$_ -le 3} {"Q1";break;}
 {$_ -le 6} {"Q2";break;}
 {$_ -le 9} {"Q3";break;}
 {$_ -le 12} {"Q4"; break;}
}


The key to this example is the Break statement. Without this, everything would match as the switch operator continues to evaluate for all possible matches (not just the first one). Break will cause it to stop evaluating.

Third example:

switch($month) {
 {$_ -ge 1 -and $_ -le 3} {"Q1"}
 {$_ -ge 4 -and $_ -le 6} {"Q2"}
 {$_ -ge 7 -and $_ -le 9} {"Q3"}
 {$_ -ge 10 -and $_ -le 12} {"Q4"}

}


The more "wordy" example with multiple conditions and the -And. This may be more readable, however the first example does a pretty good job with this. The functionality is far more obvious than example #2. In any case, using conditions to check a range of values will save time and code. Alternatively (though not very elegant or practical), you can use a regex switch for this:

switch -regex ([string]$month) {
 "^[1-3]$" {"Q1"}
 "^[4-6]$" {"Q2"}
 "^[7-9]$" {"Q3"}
 "^1[0-2]$" {"Q4"}
}

Thursday, November 19, 2015

The case of the disconnected network drive (that wasn't) who wouldn't go away

Recently I had an issue with some newly images servers having  a disconnected network drive left over on the machine.










When trying to disconnect it, it was throwing this error:
          "This network connection does not exist."

This network connection does not exist














I checked from the command prompt to see if net use could do anything with it, however it was not listed.  I tried opening the drive, and a list of files was displayed.  So in reality it wasn't disconnected after all.  I looked around on google for answers and came across a few possible registry keys that might have it:

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2
    and
HKEY_CURRENT_USER\Network

I checked these for all users and in the main HKLM tree, but there was nothing showing this entry anywhere.  Next, I used netstat -ano |find "445" to see what file sharing connections were open, and at least traced it down to a server name.  The server was related to mcafee, which is what was in the folder content as well.  Digging around a bit found the exact folder that was mapped on the machine. Trying to search the registry again with the server name didn't yield any results.

After failing with all the suggested methods of getting rid of the drive, I decided to try to disconnect it using the SYSTEM context.  So, I scheduled a task to run: net use * /delete /y, and set it to run under the SYSTEM account.  This took care of the problem and the drive is no longer showing up.

Thursday, November 12, 2015

Linux Mint user not listed on logon prompt

I tried adding a few accounts to a linux mint laptop for my kids. When using the GUI users tool, it ended up hanging when trying to create the accounts, so I went back to the normal command line tools for user creation. The accounts were created and were able to logon, by hitting esc to get a username prompt at the gui logon. When trying to find a solution for this, most people point to the UID value needing to be over 1000. The accounts that I created were 1002 and 1003, so no luck with that solution. This setting is in /etc/mdm/mdm.conf, in the [greeter] section, MinimalUID=1000. After digging around and looking at the working accounts, I noticed the command line tools missed some of the user details in /etc/passwd. Column #5 (user ID info was missing) and shell was left blank. For the working users, column #5 had the username and 3 comma's after it. After adding this to /etc/passwd, all accounts were listed as they should be.

Non-functional entry:
testuser:x:1002:1002::/home/testuser:

Functional Entry:
testuser:x:1002:1002:testuser,,,:/home/testuser:/bin/bash

Monday, October 5, 2015

McShield and Mcafee Validation Trust Protection Service start up failure [Incorrect function]

I recently encounter a server that was failing to start McShield due to its dependency service Mcafee Trust Validation Service (mfevtp) not starting.  The error was:

The McAfee Validation Trust Protection Service service terminated with the following error: 
Incorrect function.


On checking the services in the registry, I noticed some unusual keys for mfehidk followed by numbers going up to 99.  All of the keys were empty.  After deleting everything from 02 upward, mfevtp service started without error and McShield was able to start.

Tuesday, September 22, 2015

The security device (smart card) could not be used. Additional details may be available in the system event log. Please report this error to your administrator.

When trying to remote desktop into a 2012R2 server with a smart card, you may run across one of these messages:

[virtual smartcard]
"The security device could not be used. Additional details may be available in the system event log. Please report this error to your administrator."

[physical card]
"This smart card could not be used. Additional details may be available in the system even log. Please report this error to your administrator."

I ran into this sporadically on a range of machines after a 2012R2 rollout. In the event logs on the systems, a variety of smartcard logon event id 5 messages:

1) An error occurred while retrieving a digital certificate from the inserted smart card. The handle is invalid.
2) An error occurred while decrypting a message: The handle is invalid.
3) An error occurred while retrieving some provider parameter: The handle is invalid.

All having "The handle is invalid" as part of the error. After opening a case with microsoft and doing some low level tracing of the logons, they found a timeout in the smartcard crypto provider. The default for this is 1.5 seconds. After adjusting it to 5 or more seconds, the errors went away.

This is configured at HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Defaults\Provider\Microsoft Base Smart Card Crypto Provider\TransactionTimeoutMilliseconds as a DWORD. A reboot is required for this to take effect. The key can be used on other OS's as well.

I did continue to have problems with at least one machine after this, however the errors were different and quite varied. This system was on a bad network working with highly variable response times and 10% packet loss. On this same type of link, 2008R2 was more reliable for smartcard logons in comparison to 2012R2. So its always good to have some password logon backups to smartcard logons over slow links.

Remote Desktop cannot verify the identity of the remote computer because there is a time or date difference between your computer and the remote computer

I had an issue with a server that was failing to connect over RDP with the following error:

Remote Desktop cannot verify the identity of the remote computer because there is a time or date difference between your computer and the remote computer

On inspecting the machine via PSremoting, the clock time showed fine. I thought I would try connecting to RDP using the IP address. That let me through with only the normal certificate mismatch warning prompt. Looking around for solutions online usually pointed to the obvious clock problem in the error message. But again, clock time was perfectly in sync and timezone was fine as well. Another possibility given in some people's posts on this topic is the RDP certificate itself. This is located in the computer's certificate store under remote desktop\Certificates. This is automatically generated by the machine and will be recreated if deleted. I checked that, and again no issue with the certificate dates.

After digging around in the registry in HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp, I found a discrepency between this machine and another working machine. My broken machine [freshly build] had the Security value set, while the other didn't. (https://support.microsoft.com/en-us/kb/259129) Additionally this didn't match the defaultsecurity value one level up. After deleting the value and rebooting, the issue went away. Trying to reproduce the problem by putting the same value back in place only gave me the error once, then continued to let me through. So this may be something to look at if all else fails.

Server getting hammered with DistributedCOM CLSID {ECABAFB9-7F19-11D2-978E-0000F8757E2A} events

In case you have a system getting flooded with event 10014 DistrubutedCom events with this message:

The activation for CLSID {ECABAFB9-7F19-11D2-978E-0000F8757E2A} failed because remote activations for COM+ are disabled. To enable this functionality use Server Manager to install the COM+ Network Access feature in the Application Server role.

It may be caused by a remote machine trying to access the system using dcomcnfg. This event is complaining that windows feature "AS-Ent-Services" is not installed.

If this is the case, you will see RPC connections between this machine and the machine running the dcomcnfg. The remote machine will also be getting flooded by events that mention they are coming from the targeted machine.

Monday, August 3, 2015

Encouraging domain controller to advertise time

param(
[parameter(mandatory=$true)]$computer
)

$sb = {
set-itemproperty -path `
     HKLM:\system\currentcontrolset\services\w32time\timeproviders\ntpserver `
    -name "Enabled" -value "1"
restart-service w32time
w32tm /resync
}
invoke-command -script $sb -computer $computer




2023 - Update to this article. It is possible for a server to have a value of 1 on the Enabled dword
for ntserver and the server still reports that it is not advertising. There is a group policy setting
that can prevent the machine from acting as an NTP server which will block the service from working and won't
present anything obvious in the registry.

Checking NTP time offsets with powershell - parsing dos utility output

Recently I ran into a problem with domain controllers being out of sync with each other. Most of the DC's were sync'd with each other, but they had falling out of sync with the root PDC. Since SCOM's time monitoring only tests between the local system clock and the PDC of that domain, it will not detect all time problems in a multi-domain environment. In the past, this may have been fine as the windows time service had servers sync'ing to the PDC. Now there is some difference in how the time service finds a sync partner. It can be configured to use the PDC, or the new default which is based on sites (CrossSiteSyncFlags registry setting, time service reference). So, due to this problem I went through an old solution I had come up with using w32tm /monitor to look at all domain controllers. The problem with this is the output is really messy, and apparently may not be the same from one OS version to another. I had it working on 2003, and 2012R2, but when running on 2008R2 the old parsing rules I had fell apart. So using the same w32tm utility, I started over with the stripchart command to do a test of a single machine with the function below. Using this function, you can test any ntp server that is accessible (domain controller or otherwise). This way you can wrap the function into a monitoring tool that looks at all domain controllers in all domains, as well as the higher level NTP source that the domain sync's to.

The number of samples in the stripchart command will greatly impact the run time if you are running it against a large number of computers. I put it at 3 due to false non-responsive alerts when it was set to 1. If your network is repsonsive, 1 may be sufficient.


function get-timeoffset {
 param([parameter(mandatory=$true)]$computer)
 write-verbose "working on server $computer"
 $resultval = new-object PSobject
 add-member -input $resultval NoteProperty Computer $computer
 $a = w32tm /stripchart /computer:$computer /dataonly /samples:3 /ipprotocol:4
 if (-not ($a -is [array])) {
  add-member -input $resultval NoteProperty Status "Offline"
  add-member -input $resultval NoteProperty Offset $null
 } else {
  $foundtime=$false
  #go through the 5 samples to find a response with timeoffset.
  for ($i = 3; $i -lt 8; $i++) {
   if (-not $foundtime) {
    if ($a[$i] -match ", ([-+]\d+\.\d+)s") {
     $offset = [float]$matches[1] 
     add-member -input $resultval NoteProperty Status "Online"
     add-member -input $resultval NoteProperty Offset $offset
     $foundtime=$true
    } 
   }
  }
  #if no time samples were found, check for error
  if (-not $foundtime) {
   if ($a[3] -match "error") {
    #0x800705B4 is not advertising/responding
    add-member -input $resultval NoteProperty Status "NTP not responding"
   } else {
    add-member -input $resultval NoteProperty Status $a[3]
   }
   add-member -input $resultval NoteProperty Offset $null
  }
 }
 $resultval
 
}

Friday, July 24, 2015

Backing up to network share using Local System account

When using Windows Server Backup with a destination location of network share, during the schedule setup wizard it wants you to provide a user name and password.  Since normal user accounts would often change passwords, this would eventually cause backup failures.  The alternative of using service accounts is possible, but its not all that necessary and just adds to the overhead.  Using Local System (ie. the computer account) allows you to not have to worry about passwords or accounts that might get compromised (or locked out).  To set up the backup, you will need to go through the gui using an account that does have access, and has a password.  Once you have the backup scheduled, you can edit it with schtasks.

First of all, you need to set up the shared folder.  Ensure the share permissions and ntfs permissions allow both the computer account of the machine that is being backed up, and the account creating the task initially.

After this, run through the GUI wizard to schedule the backup.  This creates a scheduled task in Task Scheduler Library -> Microsoft -> Windows -> Backup.

To edit this task in schtasks.exe you will need to provide the path details in addition to the task name, which should be "Microsoft-Windows-WindowsBackup".  So the full task name is "\Microsoft\Windows\Backup\microsoft-windows-windowsbackup".

To edit it to use the System account:

C:\>schtasks /change /tn "\Microsoft\Windows\Backup\microsoft-windows-windowsbackup" /ru "nt authority\system"

SUCCESS: The parameters of scheduled task "\Microsoft\Windows\Backup\microsoft-w
indows-windowsbackup" have been changed.

Thursday, July 23, 2015

Finding domain controllers replicating from a particular server

This will look at all ntds server connections in each site to find which servers (listed in the distinguishedname attribute) are replicating from a particular machine (in the fromServer attribute).

get-adobject -searchbase `
("CN=Sites," + (get-adforest).partitionscontainer.substring(14)) `
-ldapfilter "(objectclass=nTDSConnection)" `
-Properties distinguishedname,fromServer |select distinguishedname,fromServer |
where {$_.fromserver -match "servername"}

Tuesday, June 16, 2015

FIM SSPR error 3000

One day I ran into this error on a previously working FIM 2010R2 self service password reset portal configuration instance.  All users were getting error 3000:

An error has occurred. Please try again, and if the problem persists, contact your help desk or system administrator. (Error 3000)

On the usual rounds of google, I found a few articles for testing wmi permissions and guides to ensure permissions.  The Microsoft provided install guide also covers some of this as well.  The one thing though is WMI permissions that are discussed are always root\cimv2 permissions.  When looking at my configuration, everything was already set up as it should be (according to all of these documents).  I enabled debug logging on the portal to get more details.  This showed me this message among the other related events:

System.Management: System.Management.ManagementException: Access denied
   at System.Management.ManagementException.ThrowWithExtendedInfo(ManagementStatus errorCode)
   at System.Management.ManagementScope.InitializeGuts(Object o)
   at System.Management.ManagementScope.Initialize()
   at System.Management.ManagementObjectSearcher.Initialize()
   at System.Management.ManagementObjectSearcher.Get()
   at Microsoft.ResourceManagement.PasswordReset.ResetPassword.ResetPasswordHelper(String domainName, String userName, String newPasswordText)

So obviously I still had a permissions problem somewhere.  After digging around and getting nowhere, I fell back on my favorite troubleshooting rule, "when in doubt, Netmon".

 
As you can see in the last frame, the access denied error message is present on a WMI call.  So this quickly narrows it down to a WMI issue.  Go up a few frames to the blacked out server name, and we see it accessing the root\MicrosoftIdentityIntegrationServer.  Oddly, you won't find this mentioned anywhere in the documentation.  Once I granted the service account "enable account" and "remote enable" rights on this namespace on the sync server, everything started working fine.  The root caused ended up being removal of admin rights from the fim service account on the sync server.  As usual, in bad documentation and bad troubleshooting, granting admin rights solves a lot of problems.  If you want to go with a more restricted environment, add this to your build steps for SSPR.

Just for search purposes, here are some of the other event log texts that may be seen when this issue occurs:

WorkflowInstance '3eb56c33-cc6f-4c4f-90cf-30086a5d1fbd' [Description: ] recorded the following event for activity authenticationGateActivity1.FailureBranch (type:System.Workflow.Activities.IfElseBranchActivity): Executing at 2/27/2015 6:39:02 AM.
-----------
The error page was displayed to the user.
Details:
Title: Error
Message: An error has occurred. Please try again, and if the problem persists, contact your help desk or system administrator. (Error 3000)
Source:
Attributes:
Details: System.InvalidProgramException: Error while performing the password reset operation: PWUnrecoverableError
   at Microsoft.IdentityManagement.CredentialManagement.Portal.Reset.AttemptToResetPassword()
   at System.Web.UI.WebControls.Button.OnClick(EventArgs e)
   at System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument)
   at System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument)
   at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
CorrelationId:
RequestId:
ErrorCode: 3000
CaughtTime: 02/27/2015 01:39:02

Web Portal: FIM Password Reset Portal
Session Id: mfa4tg550e52v4be0bhhxu45



-----------------

Microsoft.IdentityManagement.CredentialManagement.Portal: System.Web.HttpUnhandledException: ScriptManager_AsyncPostBackError ---> System.InvalidProgramException: Error while performing the password reset operation: PWUnrecoverableError
   at Microsoft.IdentityManagement.CredentialManagement.Portal.Reset.AttemptToResetPassword()
   at System.Web.UI.WebControls.Button.OnClick(EventArgs e)
   at System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument)
   at System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument)
   at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
   --- End of inner exception stack trace ---
   at Microsoft.IdentityManagement.CredentialManagement.Portal.Site.ScriptManager_AsyncPostBackError(Object sender, AsyncPostBackErrorEventArgs eventArgs)
   at System.Web.UI.ScriptManager.OnAsyncPostBackError(AsyncPostBackErrorEventArgs e)
   at System.Web.UI.PageRequestManager.OnPageError(Object sender, EventArgs e)
   at System.Web.UI.TemplateControl.OnError(EventArgs e)
   at System.Web.UI.Page.HandleError(Exception e)
   at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
   at System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
   at System.Web.UI.Page.ProcessRequest()
   at System.Web.UI.Page.ProcessRequest(HttpContext context)
   at ASP.default_aspx.ProcessRequest(HttpContext context)
   at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)


---------

A user's attempt to reset password ended with the following result.
The result details:
Error while performing the password reset operation: PWUnrecoverableError
Web Portal: FIM Password Reset Portal
Session Id: mfa4tg550e52v4be0bhhxu45


---------
Service fault of type DataRequiredFault was received.
----------

The web portal received a fault error from the FIM service.
Details:
Microsoft.ResourceManagement.WebServices.Faults.ServiceFaultException: DataRequiredFaultReason
   at Microsoft.ResourceManagement.WebServices.ResourceFactoryClient.Create(Message request)
   at Microsoft.IdentityManagement.CredentialManagement.Portal.Common.ResetProxy.InteractWithPasswordResetActivity(SecureString newPassword, String activityEndpoint, String workflowInstanceId, ContextualSecurityToken sessionSecurityToken)
Web Portal: FIM Password Reset Portal
Session Id: mfa4tg550e52v4be0bhhxu45




Monday, June 15, 2015

Why my child isn't on Facebook, gmail or the rest


Few people take the time to consider the actions they take online. This can be easily seen in the blind acceptance of terms of service agreements. This discussion is about my children, which are all under the age of 13. If you look at most of these major service providers, they have written rules that prohibit anyone under the age of 13 from signing up. This may be a mention in the terms of service, or it may be a technical control which checks ages based on birthdate values that are entered at sign up. Why 13? Various laws and attempts at passing laws on online child privacy (ex: COPPA) usually put special restrictions on handling privacy for children below this age. Given that these laws are being made in these company's home countries and major markets, it influences how they provide services. Having to meet various regulations for different types of users becomes expensive to create and maintain. Besides the business and the technical problems, there is the obvious issue of why these laws are being passed in the first place. Children at these ages haven't matured and are too innocent which leads them to get into trouble in these environments.

Despite the legal issues, the technical controls and the background on why they are there in the first place, kids and others are still preassuring them to sign up because "everyone is doing it", or its some necessity for class work. So for my kids, I break down the legal implications, and sometimes get into the spiritual implications. They are as follows:


Legal:

1) Terms of service agreements are contracts. Lying about your age to enter into one is fraud.

2) Terms of service agreements are contracts. Failing to follow the conditions is breech of contract.

3) The service providers are running on "protected computers". As these providers can define their systems as protected computers, any misuse of them, or unauthorised use of them violates the Computer Fraud and Abuse Act. This is criminal computer hacking.  Although this may seem ridiculous, and its unlikely that a prosecutor would pursue someone unless they were involved in other illegal or harmful activities, the law is vaguely worded and many odd uses of it have happened recently.  (Example: 14 year old arrested for changing his teacher's desktop wallpaper after teacher gave him the password [in a state with a minimum penalty of 1 year in prison].)  (Example: A woman is charged with computer hacking after creating a fake social media account to bully a teenager.)


Spiritual:

1) Lying about one's age to access a service:

"The Messenger of Allah, may Allah bless him and grant him peace, was asked, 'Can the mumin be a coward?' He said, 'Yes.' He was asked, 'Can the mumin be a miser?' He said, 'Yes.' He was asked, 'Can the mumin be a liar?' He said, 'No.' " [Muwatta]


2) Fulfilling commitments

And do not approach the property of an orphan, except in the way that is best, until he reaches maturity. And fulfill [every] commitment. Indeed, the commitment is ever [that about which one will be] questioned. [Quran 17:34]

3) Children are not allowed to enter into business transactions without assistance from a guardian who has reached the age of discernment.

4) Obeying laws
O you who have believed, obey Allah and obey the Messenger and those in authority among you. And if you disagree over anything, refer it to Allah and the Messenger, if you should believe in Allah and the Last Day. That is the best [way] and best in result. [Quran 4:59]

Computer services should be viewed in the same way that other people's property should be viewed. The service providers are paying for their equipment, maintenance and development. If it was something that belonged to your neighbour, you wouldn't help yourself to it whenever you wanted.


True taqwa is doing what is right, even when everyone is is doing wrong, or when no one will see you doing wrong.  We don't individually use our intellect to decide if a law can be broken for any reason (be it everyone else is doing it, or the law doesn't make sense, etc).

These are just a few thoughts related to the initial signing up for service. There are many other concerns later which will creep in. Its interesting that the age of 13 was chosen, given that it is around the age that children with pass into adulthood according to Islamic guidelines. Restricting internet access in the earlier ages, and providing good supervision will hopefully help establish good habits and good judgement in regard to the dangers that are out there (both physical and spiritual).

Tuesday, April 21, 2015

Active Directory ntds.dit database file size checking

This script will check the dit size, dit freespace and the drive size/freespace information on the disk that is hosting the file. It assumes that garbage collection debug logging is turned on, so that 1646 events can be read to find out how much free space is in the DIT file on each machine.

import-module activedirectory
$domaindetail = get-addomain
$domaincontrollers = $domaindetail.ReplicaDirectoryServers + $domaindetail.ReadOnlyReplicaDirectoryServers
out-default -inp ("Computername,DITsizeGB,FreespaceGB,DBDriveSize,DBDriveFreespace")
foreach ($dc in $domaincontrollers) {
 #assumes that NTDS diags for Garbage collections are set to 1
 try {
 $DITfreespace = get-winevent -FilterHashtable @{
  ID=1646;logname="Directory Service"
 } -max 1 -computername $dc |
  select -exp properties
 #value from the event log is in mb, not bytes, so we divide by kb to get gb
 $DITfreespace = $DITfreespace[0].value /1kb
 $DITfreespace = "{0:N3}" -f $DITfreespace

 #get DB location
 $RegObj = [microsoft.win32.registrykey]::openremotebasekey('LocalMachine',$dc)
 $regkey = $regobj.opensubkey("SYSTEM\\CurrentControlSet\\Services\\NTDS\\Parameters")
 $val = $regkey.getvalue("DSA Database file")
 $driveletter = $val[0] + $val[1]
 $val= $val.replace(":","$")
 $val = "\\" + $dc + "\" + $val
  
 #get size of dit
 $len = (dir \\$dc\e$\ntds\ntds.dit|select length).length /1gb
 $len = "{0:N2}" -f $len


 #get drive details
 $driveinformation = Get-WmiObject Win32_logicaldisk  -computer $dc -filter ("DeviceID = '" + $driveletter + "'")|select size,freespace
 $size = "{0:N2}" -f ($driveinformation.size /1gb)
 $freespace = "{0:N2}" -f ($driveinformation.freespace /1gb)
 out-default -inp ("$dc,$len,$DITfreespace,$size,$freespace")

 } catch {
  out-default -inp ("$dc,Failedtoconnect")
 }
}


Wednesday, April 15, 2015

(SCOM) Checking to see if AD Helper object has been installed

This script will check all of the domain controllers in the current domain for the presence of oomads (AD Helper Object). It uses jobs to help speed things up as the WMI product query is very slow. Once all jobs finish it will dump the results in csv type format.


$domaindetail = get-addomain
$domaincontrollers = $domaindetail.ReplicaDirectoryServers + $domaindetail.ReadOnlyReplicaDirectoryServers
foreach ($dc in $domaincontrollers) {
 invoke-command -computer $dc -scriptblock {
  $oomads = gwmi -query "select caption from win32_product where identifyingnumber='{3696BAB3  -3B1B-42C3-8D46-1898E59E7C84}'"|select caption
  if ($oomads -ne $null) {
   write-output -input ($env:computername + ",INSTALLED")
  } else {
   write-output -input ($env:computername + ",NOTINSTALLED")
  }
 } -asjob -jobname ("$dc-oomads")
}
#these queries are slow, so we need to wait on the jobs to finish
while ( (get-job |where {$_.name -match "oomad" -and $_.state -eq "Running"}) -ne $null) {
 sleep 30
}
get-job |where {$_.name -match "oomad"} |Receive-Job
get-job |where {$_.name -match "oomad"} |Remove-Job