Tuesday, December 27, 2016

Fixing dns record permissions for dynamic dns

In case you have dns records that need to be changed from static to dynamic, or the machine/clusters that will be updating them have changed, you can modify the dns record permissions to allow updates.  Doing this through the gui is fine for a few records, but if you need something a bit more simple and automated, you can try this script.  It takes both the computer name (doesn't have to match the dns record, just needs to be a computer object), and the dns record (fqdn) that you are updating.  This script will work for AD dns only, and would be limited to the current domain, and likely any forest wide partitions.  If you check my article on managing other domains in powershell, you can probably get edits to other domains working on this with a few modifications and extra parameters.



param (
  $computername,
  $dnsrecord
)

$script:computernameSam = $computername + "$"

try {
  import-module activedirectory
} catch {
  write-error "This script requires the AD powershell module"
  exit
}
while ( (test-path -path Ad:) -ne $true  )
{
  start-sleep -seconds 2
}

#Standard ACL for a dynamic dns entry
  #ActiveDirectoryRights : CreateChild, DeleteChild, ListChildren, ReadProperty, DeleteTree, ExtendedRight, Delete,
  #                        GenericWrite, WriteDacl, WriteOwner
  #InheritanceType       : None
  #ObjectType            : 00000000-0000-0000-0000-000000000000
  #InheritedObjectType   : 00000000-0000-0000-0000-000000000000
  #ObjectFlags           : None
  #AccessControlType     : Allow
  #IdentityReference     : Domain\machine$
  #IsInherited           : False
  #InheritanceFlags      : None
  #PropagationFlags      : None
# 

function get-partition {
  param ( $record )
  #need to split off everything after first name to find longest zone match
  #using get-dnsserverzone ($name)
  
  $dnsrecordparts = $record.split(".")
  
  for ($i = 1; $i -lt $dnsrecordparts.length; $i++) {
    $zonenameTest = $dnsrecordparts[$i..($dnsrecordparts.length -1)] -join "."
    $zoneObj = get-dnsserverzone $zonenameTest -ea 0
    if ($zoneObj -ne $null) {
    write-output -inputobject $zoneobj
    $i = $dnsrecordparts.length + 1
    }
  }
  
}

function get-dnsobject {
  param ($record)
  $zoneObject = get-partition -record $record
  if ($zoneObject -ne $null) {
    $zonename = $zoneObject.zonename
    $record -match "(.*)(\.$zonename)"
    $dnsRecordDN = "dc=" + $matches[1] + "," + $zoneobject.distinguishedname
     try {
       get-adobject  $dnsRecordDN
    } catch { Throw "Unable to find dns record for this machine"}
  } else { throw "DNS zone not found"}
}

try {
  try {
    $guid = [guid]'00000000-0000-0000-0000-000000000000'
    $adcomputer = get-adcomputer $computername -property objectsid
    $sid = $adcomputer.objectsid
    $ctrl = [System.Security.AccessControl.AccessControlType]::Allow
    $rights = 983423
    $intype =[System.DirectoryServices.ActiveDirectorySecurityInheritance]::None
    $rule = New-Object System.DirectoryServices.ActiveDirectoryAccessRule($sid,$rights,$ctrl,$guid)
  } catch { throw "Unable to get computer account SID" }

  try {
    #find record
    $dnsDN = get-dnsObject -record $dnsrecord
  } catch { throw $_ }
  
  try {
    $acl = get-acl ad:"$($dnsDN.distinguishedname)"
    $acl.setowner([system.security.principal.ntaccount]"$script:computernameSam")
    $acl.AddAccessRule($rule)
    Set-Acl -acl $acl -path ad:"$($dnsDN.distinguishedname)"
  } catch { throw $_ }

} catch { $_}

Wednesday, December 21, 2016

DNS - limited forwarding delegated subdomain (in AD integrated zone)

If you find yourself in need to creating subdomains off of an existing AD integrated zone, which forward externally, you may encounter the problem that not all AD dns servers can access an external set of servers. To limit the domain controllers that do dns forwarding, while still allowing all dc's to know how to resolve records, you can combine delegated subdomains and conditional forwarders (non-AD integrated).

Example:

-Organization has AD integrated zone Contoso.com on all AD domain controllers.
-Organization is outsourcing dns for subdomain hosting.contoso.com to external domain name servers
-Only 2 out of 50 domain controllers can access external dns for name resolution.  All others do general forwarding to these 2 domain controllers.

Problem:
1) If we create a delegation in contoso.com directly to the external dns servers, recursion is not available and name resolution is not going to happen.
2) if we create AD integrated conditional forwarding for the subdomain, all servers will try to forward to external dns and will be unable to do so, causing queries to fail

Solution:
-Create a subdomain delegation in contoso.com using only the name servers of the 2 internal domain controllers that have access to forward dns queries to external servers
-Create non-AD integrated conditional forwarders for hosting.contoso.com on these same 2 servers, which use the dns server IP's of the external dns provider
-On the external provider, set up a dns zone for hosting.contoso.com

Wednesday, December 14, 2016

Learn typing on arabic keyboards

When trying to find a decent place to learn how to type arabic, I found a lot of sad looking websites that either didn't have what the search results suggested, or they only showed a few phrases to practice on. Most are more oriented as online keyboards for you to type and paste with. Since most operating systems provide alternate keyboards and easy switching between them, for anyone who seriously needs to type arabic, it would be great to have some alternative. So I thought I would put together something simple with lessons that goes through a touch typing style learning methodology. You can try it here: Arabic typing - free online course.

Tuesday, December 6, 2016

SCCM windows update deployment failure 0x80240438

Windows update problem caused by web troubleshooting tools and system proxy. Netsh winhttp settings were creating a local proxy that was not causing any issues in the user context, but in the system context, it was breaking outbound web connections. SCCM logs only showed the error code, but not much useful information beyond that. WindowsUpdate.log contained a clear message on the attempted use (and failure) of a proxy.

wuauhandler.log

<![LOG[OnSearchComplete - Failed to end search job. Error = 0x80240438.]LOG]!><time=".." date=".." component="WUAHandler" context="" type="3" thread="2744" file="cwuahandler.cpp:3223">
<![LOG[Scan failed with error = 0x80240438.]LOG]!><time=".." date=".." component="WUAHandler" context="" type="3" thread="2744" file="cwuahandler.cpp:3679">

updateshandler.log

<![LOG[Updates scan completion received, result = 0x80240438.]LOG]!><time=".." date=".." component="UpdatesHandler" context="" type="1" thread="9884" file="capplicabilityhandler.cpp:100">


updatesdeployment.log

<![LOG[Job error (0x80240438) received for assignment ({guid}) action]LOG]!><time=".." date=".." component="UpdatesDeploymentAgent" context="" type="3" thread="7056" file="updatesassignment.cpp:2235">


scanagent.log

<![LOG[ScanJob({guid}): CScanJobManager::OnScanComplete- failed at CScanJob::OnScanComplete with error=0x80240438]LOG]!><time=".." date=".." component="ScanAgent" context="" type="3" thread="11024" file="utils.cpp:537">


ciagent.log

<![LOG[Failed result received from applicability handler, error = 0x80240438]LOG]!><time=".." date=".." component="CIAgent" context="" type="3" thread="7056" file="capplicabilitybroker.cpp:79">


WindowsUpdate.log

yyyy-mm-dd hh:mm:ss 1068 30a4 WS WARNING: Web service call failed with hr = 80240438.
yyyy-mm-dd hh:mm:ss 1068 30a4 WS WARNING: Current service auth scheme='None'.
yyyy-mm-dd hh:mm:ss 1068 30a4 WS WARNING: Proxy List used: '127.0.0.1:8888', Bypass List used: '(null)', Last Proxy used: '127.0.0.1:8888', Last auth Schemes used: 'None'.
yyyy-mm-dd hh:mm:ss 1068 30a4 WS FATAL: OnCallFailure failed with hr=0X80240438
yyyy-mm-dd hh:mm:ss 1068 30a4 WS WARNING: NWS retry 1 for transient error 0x80240438
yyyy-mm-dd hh:mm:ss 1068 30a4 WS WARNING: Nws Failure: errorCode=0x803d0010
yyyy-mm-dd hh:mm:ss 1068 30a4 WS WARNING: There was an error communicating with the endpoint at 'http://deploymentserver:8530/ClientWebService/client.asmx'.
yyyy-mm-dd hh:mm:ss 1068 30a4 WS WARNING: The given proxy cannot be reached.

------------------------------------------
netsh winhttp>show proxy

Current WinHTTP proxy settings:
Proxy Server(s) : 127.0.0.1:8888
Bypass List : (none)

Wednesday, September 28, 2016

Masjid Nabawi (Madinah) - Tips



-Getting in the front saf.  The masjid’s actual front saf is in the older (more narrow) front section of the masjid.  Due to the rawdah and other attractions in that part of the masjid, its often very full and sectioned off.  Trying to pray inside the masjid in the front saf is nearly impossible, and if you do manage to get it, it is tightly packed and hard to focus.  Try to try get there for fajr, look at going by midnight and don’t leave for any reason (don’t break wudu).  The easier way to pray in the front is outside.  In the picture above you can see the mark on the right side of the masjid where I say its an easy front row position.  This side of the masjid is longer than the left side.  Usually there are carpets set up there, and if not, there are block lines marking rows.  There are some information screens that point out not try pray in front of a certain point to avoid being in front of the imam.  That is the line of umbrellas with the double black line running just behind them.  It is a bit warm out there, but they do have the umbrellas, and some water fans (that rarely seem to blow in your direction).  During zuhr and asr, either the umbrellas don’t filter UV or the reflection of the sun on the marble carries it, so if you’re out there for a while and get sunburn easily, make sure you put on sunscreen.  The good news is, you can still get in the front row 30 min before solat.

-Following the funeral to baqi (men only).  Since almost every solat in this masjid is followed by the funeral prayer, you can increase your rewards by following the procession into baqi and helping carry and bury the body(s).  You need to be fast for this, and in the right areas of the masjid.  The bodies come out right after solat from a door in front of where the imam is positioned.  The best place to be is on the left side of the masjid (outside), or inside and very close to Bab Bilal.  Getting to Bab Bilal from the inside of the masjid can be blocked off at times.  When they have the rawdah open to women, there will be barriers blocking you from walking in that direction.  Those will be removed at least an hour before an fard solat.  You can be on the right side (outside), but you need to run as soon as the funeral prayer is over.  If you are a bit far on the right, you may want to use the short break between the fard solat and the janazah prayer to move farther to the left and jump in a saf somewhere closer to the funeral exit.  If you’re too far behind the procession, the gates of baqi will be closed on you and you can’t get in.  The whole burial/walking takes at least 30 minutes.  It will be very dusty and dirty.  Due to the wind and the soft sand, you will end up in a mini sandstorm when the grave is being filled.  Make sure you have a water bottle with you because once you get inside baqi there’s usually a steady and very dry hot wind.

-Quran teaching.  There will be many teachers that set up quran circles in the masjid.  If I remember correctly, this started at least an hour before asr, and more towards the front right of the newer section of the masjid.  They might be in other places as well.  These are free and open classes where the teacher will invite anyone nearby to come and practice recitation.

-Halaqahs.  There is one American scholar (Tahir Wyatt) who gives a halaqah in english between magrib and isha for brothers.  This is located near the right rear brother’s entrance.  Once you go in the door, turn left and go a short distance.  The chair is at the very back of the masjid.

-Friday sermon in other languages.  If you have a radio with you (or phone that does radio), there are several translated versions of the khutbah being broadcast.  This is both in madina and mecca.  I couldn’t find a list of frequencies this time, but I believe english in madina was 105.5, and for mecca it was something around 102.  You won’t be able to find the stations very easily in advance of the beginning of the sermon, but look for radio frequencies that are broadcasting silence instead of static.  There should be at least 4 of them.

-zam zam.  I’m not 100% sure on this, but there are a lot of wudu and drinking water places around the outside of the masjid at the mini buildings that you see all around it.  I thought this might be zam zam, but most likely it is just drinking water.  There is occasionally a mobile metal water tank set up outside with taps on it which would be zam zam.  Otherwise, all throughout the masjid, they have the coolers set up.

-rawdah.  Trying to get in here before a fard solat is very difficult as people are going in there to stay.  The crowds are always large.  Trying to get in around the middle of the night for a short amount of time might be possible.  In these times, people will usually give you some space if you indicate you just want to pray a few rakats there.


-Praying inside.  The masjid fills up quickly in the back, but not so much in the front or middle.  If you don’t want to have to move forward 10 or more saf’s just as the prayer begins, pray directly behind a column.  This has the added benefit of being near aircon, and less of a chance that people will walk in front of you during any sunnah prayers you may want to pray.  You should start your position more towards the front though to help avoid being part of the “gap” problem.

Thursday, July 28, 2016

MS - Certificate autoenrollment behind a firewall

For anyone who has autoenrollment for certificates on machines that are behind firewalls, here are the ports and servers you want to look at for setting up firewall rules:


Client to domain controller:
    Kerberos port 88 (UDP/TCP)
    Ldap (TCP 389)
    RPC (tcp 135)
    RPC on dynamic port (>1023 TCP)

Client to certificate server(s) with the template available 
    RPC (TCP 135)
    Dynamic RPC (TCP > 1023) for CA servers on windows 2003 and earlier
    Dynamic RPC (TCP > 49151) for CA servers on newer windows OS's


If you want to find the specific port that the certificate services server is listening on for RPC requests, you can find it in several different ways.  If you have access to logon to the server, you can use:

tasklist /svc |find /I "Certsvc"

In that output, look at the process ID number and use it in the command below.  If the port is 52775, use:

netstat -ano |find "LISTEN" | Find "52775"


If you do not have access to logon to the server to run these commands and you have access to the old windows resource kit files, you can use RPC dump to look for the uuid 91ae6020-9e3c-11cf-8d7c-00aa00c091be.  Use:

rpcdump /S nameofremoteserver /I /v /P ncacn_ip_tcp.

This will output more than what you need, so search through the output to find the guid in the UUID field.  The port will be what is listed as the Endpoint, or in the StringBinding.


ProtSeq:ncacn_ip_tcp
Endpoint:52775
NetOpt:
Annotation:
IsListening:YES
StringBinding:ncacn_ip_tcp:computername[52775]
UUID:91ae6020-9e3c-11cf-8d7c-00aa00c091be
ComTimeOutValue:RPC_C_BINDING_DEFAULT_TIMEOUT
VersMajor 0 VersMinor 0


Once you have obtained the port, you can use any port testing tool from the client to the CA server, like test-netconnection to see if that port, and port 135 is accessible to the client. 

Thursday, July 21, 2016

"SSLv3 Information Disclosure Vulnerability" - Dell Openmanage

If you have vulnerability scanners flagging systems for SSLv3 related vulnerabilities, check your Dell OMSA version. Versions earlier than 8.x are configured with weaker protocols, as seem in the server.xml in \program files\dell\sysmgt\apache-tomcat\conf

OMSA 8.x

<Connector compression="force" SSLEnabled="true" clientAuth="false" keystoreFile="conf/keystore.db" keystorePass="${keystore_password}" keyPass="${key_password}" maxThreads="150" maxPostSize="6291456" port="1311" protocol="org.apache.coyote.http11.Http11NioProtocol" scheme="https" secure="true" sslEnabledProtocols="TLSv1,TLSv1.1,TLSv1.2" ciphers="TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA"/>

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

OMSA 7.x

<-- <Connector port="1311" protocol="HTTP/1.1" SSLEnabled="true" maxThreads="150" scheme="https" secure="true" clientAuth="false" sslProtocol="TLS" /> --> <Connector compression="force" SSLEnabled="true" address="*" clientAuth="false" keystoreFile="conf/keystore.db" keystorePass="${keystore_password}" keyPass="${key_password}" maxThreads="150" maxPostSize="6291456" port="1311" protocol="HTTP/1.1" scheme="https" secure="true" sslProtocol="TLS" ciphers="SSL_RSA_WITH_RC4_128_SHA,SSL_RSA_WITH_RC4_128_MD5,SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA,TLS_DHE_RSA_WITH_AES_128_CBC_SHA,SSL_RSA_WITH_3DES_EDE_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_DHE_DSS_WITH_AES_128_CBC_SHA,SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA"/>



You can test SSLv3 connections with openssl.

Server with OMSA 8.3

C:\>openssl s_client -connect OMSA8server-ssl3 Loading 'screen' into random state - done CONNECTED(00000230) 12252:error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number:./ssl/s3_pkt.c:284:

Server with OMSA 7.3

C:\>openssl s_client -connect OMSA7Server:1311 -ssl3
Loading 'screen' into random state - done
CONNECTED(00000230)
depth=0 /C=US/ST=TX/L=Round Rock/OU=SA Enterprise Software Development/O=Dell Inc/CN=OMSA7Server
verify error:num=18:self signed certificate
verify return:1
depth=0 /C=US/ST=TX/L=Round Rock/OU=SA Enterprise Software Development/O=Dell Inc/CN=OMSA7Server
verify return:1
*snip*
New, TLSv1/SSLv3, Cipher is EDH-RSA-DES-CBC3-SHA
Server public key is 2048 bit
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : SSLv3
Cipher : EDH-RSA-DES-CBC3-SHA
Session-ID: 57901ECD7AE62B7F65EFA4160F2106E5ED39AB0BC5E53FEA6AD8359F7DC01AAB


Session-ID-ctx:
Master-Key: B37B02F7037C019E471A564F56629C1FBF45967F120DF631A15DCA048202CD2F069C9628116DAA00BB93466EDF5FA2E8
Key-Arg : None
Start Time: 1469062860
Timeout : 7200 (sec)
Verify return code: 18 (self signed certificate)
---

"TLS/SSL RC4 Cipher Suites Information Disclosure Vulnerability" Dell OpenManage

If you have vulnerability scanners flagging systems for RC4 related vulnerabilities, check your Dell OMSA version. Versions earlier than 8.x are configured with weaker protocols, as seem in the server.xml in \program files\dell\sysmgt\apache-tomcat\conf

OMSA 8.x

<Connector compression="force" SSLEnabled="true" clientAuth="false" keystoreFile="conf/keystore.db" keystorePass="${keystore_password}" keyPass="${key_password}" maxThreads="150" maxPostSize="6291456" port="1311" protocol="org.apache.coyote.http11.Http11NioProtocol" scheme="https" secure="true" sslEnabledProtocols="TLSv1,TLSv1.1,TLSv1.2" ciphers="TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA"/>

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

OMSA 7.x

<-- <Connector port="1311" protocol="HTTP/1.1" SSLEnabled="true" maxThreads="150" scheme="https" secure="true" clientAuth="false" sslProtocol="TLS" /> --> <Connector compression="force" SSLEnabled="true" address="*" clientAuth="false" keystoreFile="conf/keystore.db" keystorePass="${keystore_password}" keyPass="${key_password}" maxThreads="150" maxPostSize="6291456" port="1311" protocol="HTTP/1.1" scheme="https" secure="true" sslProtocol="TLS" ciphers="SSL_RSA_WITH_RC4_128_SHA,SSL_RSA_WITH_RC4_128_MD5,SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA,TLS_DHE_RSA_WITH_AES_128_CBC_SHA,SSL_RSA_WITH_3DES_EDE_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_DHE_DSS_WITH_AES_128_CBC_SHA,SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA"/>



You can test cipher's with openssl. The example below is RC4-MD5. The format of available cipher commands in openssl is different than the tomcat configurations above. You can run "openssl ciphers" to get the list.

Server with OMSA 8.3

C:\>openssl s_client -connect OMSA8Server:1311 -cipher RC4-MD5
Loading 'screen' into random state - done
CONNECTED(00000234)
11868:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake failure:./ssl/s23_lib.c:188:


Server with OMSA 7.3

C:\>openssl s_client -connect OMSA7Server:1311 -cipher RC4-MD5
Loading 'screen' into random state - done
CONNECTED(00000230)
depth=0 /C=US/ST=TX/L=Round Rock/OU=SA Enterprise Software Development/O=Dell Inc/CN=OMSA7Server
verify error:num=18:self signed certificate
verify return:1
depth=0 /C=US/ST=TX/L=Round Rock/OU=SA Enterprise Software Development/O=Dell Inc/CN=OMSA7Server
verify return:1
---
Certificate chain
0 s:/C=US/ST=TX/L=Round Rock/OU=SA Enterprise Software Development/O=Dell Inc/CN=OMSA7Server
i:/C=US/ST=TX/L=Round Rock/OU=SA Enterprise Software Development/O=Dell Inc/CN=OMSA7Server
---
Server certificate
-----BEGIN CERTIFICATE-----
***
-----END CERTIFICATE-----
subject=/C=US/ST=TX/L=Round Rock/OU=SA Enterprise Software Development/O=Dell Inc/CN=OMSA7Server
issuer=/C=US/ST=TX/L=Round Rock/OU=SA Enterprise Software Development/O=Dell Inc/CN=OMSA7Server
---
No client certificate CA names sent
---
SSL handshake has read 1044 bytes and written 359 bytes
---
New, TLSv1/SSLv3, Cipher is RC4-MD5
Server public key is 2048 bit
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1
Cipher : RC4-MD5
Session-ID: 57901EA40CB03FB263CDC30D1B77107D9B872C0BB8D9DF655981A3AA3DA67C94


Session-ID-ctx:
Master-Key: 707E2C192E1ED22E22684CBEF9B1EC139F6EA00456AFE5B6E473242064006D9C86F3D85E0CBAEC39697D82CE65F6BA4D
Key-Arg : None
Start Time: 1469062820
Timeout : 300 (sec)
Verify return code: 18 (self signed certificate)
---

Tuesday, June 21, 2016

Tips for AD group membership managment in powershell

Managing large groups can fail due to limits in Active Directory Web Services when too many members are in a group.

Fails: Get-adgroupmember "LargeGroup"
       error:  Get-ADGroupMember : The size limit for this request was exceeded

Works:  Add-adgroupmember and remove-adgroupmember

Work Around: get-adgroup "LargeGroup" -properties members | select -expand members

This will get the distinguishednames of all members as an array.

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

Piping groups or users into a group membership cmdlet to change the group memberships.

1) When you are piping groups into a cmdlet where the user(s) are static.  Pipe to Add-ADGroupMember.
    Ex:  get-adgroup -filter {name -like "HelpDesk*"}| add-adgroupmember -members $userdn

2) When you are piping users into a cmdlet where the group(s) are static.  Pipe to Add-ADPrincipalGroupMembership
    Ex: get-aduser bob | Add-ADPrincipalGroupMembership -memberof $groupdn

NOTE: Add-ADPrincipalGroupMembership will generate successful security audit events (Directory Service Change) for the addition of the group member, even if they were already a member of the group

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

When using Add-ADGroupMember with an array of members, if any of them are part of the group already, the whole operation will fail.  Its best to try adding one at a time.

Thursday, June 16, 2016

Piping get-aduser output through several custom powershell functions

For people who write scripts to process large amounts of AD objects, you may find that use of pipelines will be more memory efficient that variables and foreach. In one case, I was working through a problem with a script in powershell v2, where lots of strange failures were occurring, such as failing to assign values to a variable. A statement like: $a = 1, may just randomly not work. As the script was doing some heavy processing of large numbers of objects, I assumed memory consumption was the problem. I wanted to convert the script to use of pipeline. Since the script had several functions that handled different aspects of what was needed, I thought it would be good to try multiple pipelines. In the end, the change to pipelines fixed all the failures in the script.

What I wanted:

Take an OU, run get-aduser on the OU -> Pipe to an analysis function to check password expiration for different types of accounts and password policies, then decide if an email notice needed to be sent -> Pipe (if needed) to an email function -> Pipe the results of all of the above to logging function.

At each stage, different bits of calculated data or additional properties needed to be added to the original get-aduser object. This was possible by using custom PSObjects after the initial analysis function. The basics of the code is below:

function process-OU { 
 param(  
  [parameter(mandatory=$true)][string]$searchbase, 
  [string]$type="standard"
 )
 Get-ADUser -Filter {(enabled -eq $True) -and (mail -like "*") } `
      -SearchBase $SearchBase `
      -Properties mail, PasswordLastSet, sn, PasswordNeverExpires | 
           analyze-user -type $type |email-user |log-result
}

function Analyze-User{
 [CmdletBinding()]
 param (
  [Parameter(Mandatory=$True,ValueFromPipeline=$True)]
    [Microsoft.ActiveDirectory.Management.ADAccount]$user,
  [string]$Type
 )
 begin {}
 process {
  #do some analysis and decide if you want to 
                #continue with write-output $user
  #
  #Add any additional pieces of information to the user object with
  #   add-member -input $user -force NoteProperty Expired $False
  if ($proceedtoEmail) { write-output $user } 
 }
}

function Email-User {
 [CmdletBinding()]
      Param(  
        [Parameter(Mandatory=$True,ValueFromPipeline=$True)]
        [PSobject]$emailuser  
      )
    #Notice the parameter type is a generic 
    #[psobject] as it is no long conforming 
    #to the [Microsoft.ActiveDirectory.Management.ADAccount] type
 Begin{}
 Process {
  #handle email creation and sending.  
                #Check if it was sent without error, 
                #add email status as another property
 }
}

function log-result {
 [CmdletBinding()]
         Param(   
            [Parameter(Mandatory=$True,ValueFromPipeline=$True)]
              [PSObject]$user   
        )
 begin {}
 process {
  #do some logging here
 }
}


process-OU -searchbase "ou=myusers,dc=contoso,dc=com" -type "regular"

Wednesday, April 27, 2016

Start menu won't open in Windows 10 Home

Recently my kids were complaining that they needed Microsoft Office for their school work, and libre office wasn't compatible enough with what they wanted to do.  So we had to get a new machine to have something that would run Windows.  Within the first week, one of the kids managed to do something to screw up his user profile to the point that it took several minutes to logon.  Once on, the start menu wouldn't open, half of the task bar tray icons weren't working, and none of them would give any menu's when right clicking.

In the event logs, they were full of ESENT events:

Event 465: ESENT

svchost (2972) TILEREPOSITORYS-1-5-21-1971466138-3024181641-1488003878-1003: Corruption was detected during soft recovery in logfile C:\Users\thekid\AppData\Local\TileDataLayer\Database\EDB.log. The failing checksum record is located at position END. Data not matching the log-file fill pattern first appeared in sector 279 (0x00000117). This logfile has been damaged and is unusable.

Event 477: ESENT

svchost (2972) TILEREPOSITORYS-1-5-21-1971466138-3024181641-1488003878-1003: The log range read from the file "C:\Users\thekid\AppData\Local\TileDataLayer\Database\EDB.log" at offset 1142784 (0x0000000000117000) for 4096 (0x00001000) bytes failed verification due to a range checksum mismatch.  The expected checksum was 9075318455674107058 (0x7df2020d660074b2) and the actual checksum was 9075318455674107058 (0x7df2020d660074b2). The read operation will fail with error -501 (0xfffffe0b).  If this condition persists then please restore the logfile from a previous backup.

Event 454: ESENT

svchost (2972) TILEREPOSITORYS-1-5-21-1971466138-3024181641-1488003878-1003: Database recovery/restore failed with unexpected error -501.

When I went into Settings -> Accounts -> Family & other users area to try to delete the account, the only options are change account type and block.  To actually delete it, I had to use the "Manage family settings online" option.  Under the more menu pull down, there is an option to remove from family.  This shifts the account from "Your Family" down to "Other Users", where you will have an option to remove them from the machine once you click on the name.  It takes a bit of time to wipe out their profile, but once its done, their user account folder is empty.

As some Microsoft people will write, user profile corruption really doesn't exist, but in reality it happens a lot.  Windows 10 seems to be pretty sensitive to it and fails catastrophically.  I wish schools would just use free office apps so we can stick to Linux.

There are several write ups that could help resolve this type of problem if you go searching for the specific event ID's above.  If you just search for the start button not working, the tips you may come across seem pretty useless.  Deleting a user account has its own issues (loss of data, or requirement to backup before doing so).  For some other methods of dealing with this issue check out this post.

Tuesday, April 12, 2016

Active Directory ACL's explained

In a previous post on decoding AD ACL's, I provided some code which took BSonPosh's get-adacl output and decoded the SID's and GUID's to help provide more readable output.  The example of this is below, however you may find some of the other fields to be a bit confusing.  So I created a few different types of test permissions on an OU to show how they are reflected in the Powershell output of these two commands.


Permission set in GUI: "Apply to: All Descendant objects, create/delete Conference Site objects"

ActiveDirectoryRights :  CreateChild, DeleteChild
InheritanceType       :     Descendents
ObjectType            :      msExchConferenceContainer
InheritedObjectType   :   00000000-0000-0000-0000-000000000000
ObjectFlags           :       ObjectAceTypePresent
AccessControlType     : Allow
IdentityReference     :    TEST.LOCAL\Nathan
IsInherited           :        False
InheritanceFlags      :    ContainerInherit
PropagationFlags      :   InheritOnly

Permission set in GUI:  "Apply to: This object and all descendant objects, create/delete Contact objects"

ActiveDirectoryRights : CreateChild, DeleteChild
InheritanceType       :    All
ObjectType            :     contact
InheritedObjectType   : 00000000-0000-0000-0000-000000000000
ObjectFlags           :      ObjectAceTypePresent
AccessControlType     : Allow
IdentityReference     :     TEST.LOCAL\Nathan
IsInherited           :        False
InheritanceFlags      :    ContainerInherit
PropagationFlags      :   None

Permission set in GUI:  "Apply to: This object only, create/delete Computer Objects"

ActiveDirectoryRights : CreateChild, DeleteChild
InheritanceType       :    None
ObjectType            :     computer
InheritedObjectType   : 00000000-0000-0000-0000-000000000000
ObjectFlags           :     ObjectAceTypePresent
AccessControlType     : Allow
IdentityReference     :    TEST.LOCAL\Nathan
IsInherited           :        False
InheritanceFlags      :    None
PropagationFlags      :  None

Permission set in GUI:   "Apply to: Descendent Computer objects, Modify Owner"

ActiveDirectoryRights : WriteOwner
InheritanceType       :    Descendents
ObjectType            :     00000000-0000-0000-0000-000000000000
InheritedObjectType   : computer
ObjectFlags           :      InheritedObjectAceTypePresent
AccessControlType     : Allow
IdentityReference     :    BHI-MASTER\adminlinlnat
IsInherited           :        False
InheritanceFlags      :    ContainerInherit
PropagationFlags      :  InheritOnly

InheritedObjectType:  Notice this will be all zero's when the permission is for creating a child object in a container.  When it is permissions being set on a specific type of child objects, then it will be set that that object type, and the ObjectType value will be all zero's.  When setting a permission on a specific property of a specific type of child object, you will get both fields filled in with the ObjectType being the specified property, and InheritedObjectType being the AD object's type.

PropagationFlags: InheritOnly exists when applying to something other than the current OU.  (https://msdn.microsoft.com/en-us/library/system.security.accesscontrol.propagationflags(v=vs.110).aspx)

InheritenceFlags: ContainerInherit when applying to anything below the current level, ObjectInherit when applying to child objects (https://msdn.microsoft.com/en-us/library/system.security.accesscontrol.inheritanceflags(v=vs.110).aspx)

InheritanceType: All (everything from this level down), Descendents (children and descendants, not the current object), None (current level only)   (https://msdn.microsoft.com/en-us/library/system.directoryservices.activedirectorysecurityinheritance(v=vs.110).aspx)