<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="https://www.w3.org/2005/Atom" xmlns:sy="https://purl.org/rss/1.0/modules/syndication/" xmlns:dc="https://purl.org/dc/elements/1.1/" xmlns:content="https://purl.org/rss/1.0/modules/content/" xmlns:wfw="https://wellformedweb.org/CommentAPI/" xmlns:slash="https://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>The PFE Exchange</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/schrimsher/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/schrimsher/feed.xml</link>
    <description>Tips and tricks relating to Exchange and Office 365</description>
    <lastBuildDate>Fri, 29 Dec 2017 19:34:27 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Guest Author Series: Securely Publishing EAC</title>
      <link>https://docs.microsoft.com/archive/blogs/schrimsher/guest-author-series-waller-securely-publish-eac</link>
      <pubDate>Tue, 26 Sep 2017 19:06:02 GMT</pubDate>
      <dc:creator><![CDATA[Chris Schrimsher]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/schrimsher/?p=106</guid>
      <description><![CDATA[Good day, everyone!  A common question we hear from customers is "How do I selectively disable...]]></description>
      <content:encoded><![CDATA[<p style="padding-left: 30px"><em>Good day, everyone!  A common question we hear from customers is "How do I selectively disable access to the Exchange Administrative Center (e.g. from the Internet or well known internal URLs) while still allowing the /ecp virtual directory for features needed by standard users?"  A long time friend of mine (and one of the smartest geeks I know) wrote some content a while back that has been critically acclaimed by his customers and I wanted to share it here.</em></p>
<p style="padding-left: 30px"><em>Without further ado, ladies and gentlemen, let's hear it for <strong>Butch Waller</strong>!</em></p>


<hr />

The formal guidance for disabling administrative access to the EAC for users coming in from the Internet is found here - <a href="https://technet.microsoft.com/en-us/library/jj218639(v=exchg.150).aspx">https://technet.microsoft.com/en-us/library/jj218639(v=exchg.150).aspx</a>. In that guidance, the suggestion is that the only method of achieving this is to "<em>install a separate CAS server and configure it to only handle internal requests</em>". While this is certainly an expeditious way to accomplish the task, it brings with it additional Exchange and Windows Server licensing along with the extra servers to update.

Based on a modified version of the advice we have given Exchange customers over the years to create a second OWA virtual directory to accommodate FBA authentication behind an ISA/TMG firewall, I believe we can accomplish the desired outcome without the need for additional servers.

Henrik Walther (who has worked for Microsoft for the last couple of years now) published a great series of articles on that original guidance I mentioned above on MSExchange.org - <a href="https://www.msexchange.org/articles-tutorials/exchange-server-2010/management-administration/enabling-forms-based-authentication-external-internal-owa-2010-users-exchange-2010-published-using-forefront-tmg-2010-part1.html">https://www.msexchange.org/articles-tutorials/exchange-server-2010/management-administration/enabling-forms-based-authentication-external-internal-owa-2010-users-exchange-2010-published-using-forefront-tmg-2010-part1.html</a>. It is a great idea to digest that information before proceeding.

Here are the steps I have processed through in my lab to accomplish administrative separation in the ECP website:
<ul>
 	<li>Add a second internal IP address to the CAS
<ul>
 	<li>If you have an unused NIC on the server, leverage it to add a second internal IP address</li>
 	<li>If no second NIC, add a second IP address in the advanced properties of Ipv4 on the NIC</li>
</ul>
</li>
 	<li>Determine the internal only name you want to give the new website - e.g. <em>contoso.com</em>
<ul>
 	<li>Create an A record in DNS to point the new internal website name to the second IP address</li>
</ul>
</li>
 	<li>On each server with the CAS role, open IIS Manager and create a new website. Any site name is acceptable.</li>
</ul>
<a href="https://msdnshared.blob.core.windows.net/media/2017/09/intecp1.jpg"><img width="1024" height="748" class="alignnone wp-image-145 size-large" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/09/intecp1-1024x748.jpg" /></a>
<ul>
 	<li>Run the commands to create the new virtual directories
<ul>
 	<li>New-OWAVirtualDirectory -Server CON-E2013CAS -WebSiteName "IntECP"</li>
 	<li>New-ECPVirtualDirectory -Server CON-E2013CAS -WebSiteName "IntECP"</li>
</ul>
</li>
</ul>
<ul>
 	<li>Set the Internal URL value on both OWA and ECP virtual directories to the new namespace
<ul>
 	<li><a href="https://internal.contoso.com/owa">https://internal.contoso.com/owa</a></li>
 	<li><a href="https://internal.contoso.com/ecp">https://internal.contoso.com/ecp</a></li>
</ul>
</li>
</ul>
<a href="https://msdnshared.blob.core.windows.net/media/2017/09/intecp2.jpg"><img width="1024" height="772" class="alignnone size-large wp-image-107" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/09/intecp2-1024x772.jpg" /></a>
<ul>
 	<li>Add the new name to the Exchange server certificate that will be assigned the IIS service
<ul>
 	<li>Import the certificate</li>
 	<li>Assign the IIS service to the new certificate and test access to:
<ul>
 	<li><a href="https://internal.contoso.com/ecp">https://internal.contoso.com/ecp</a></li>
</ul>
</li>
</ul>
</li>
</ul>
<a href="https://msdnshared.blob.core.windows.net/media/2017/09/intecp3.jpg"><img width="1024" height="997" class="alignnone size-large wp-image-165" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/09/intecp3-1024x997.jpg" /></a>
<ul>
 	<li>Run the EMS command to disable full administrative access to the original ECP virtual directory in the Default Web Site
<ul>
 	<li><strong><em>Set-ECPVirtualDirectory "CON-E15CAS\ecp (Default Web Site)" -AdminEnabled $False</em></strong> (users will still be able to access their mailbox options page via this site)</li>
</ul>
</li>
 	<li>Verify access to the following:
<ul>
 	<li><a href="https://mail.contoso.com/ecp">https://mail.contoso.com/ecp</a> - mailbox options only</li>
 	<li><a href="https://internal.contoso.com/ecp">https://internal.contoso.com/ecp</a> - full EAC interface</li>
</ul>
</li>
</ul>
With this in place, you can notify all Exchange admins in the environment about the new admin URL. Since this is only published inside the corporate network, administrative access will only be accomplished while on the LAN locally or via VPN, but the threat of compromised admin credentials is greatly reduced!

&nbsp;]]></content:encoded>
    </item>
    <item>
      <title>Counting and/or identifying unique instances of things in PowerShell</title>
      <link>https://docs.microsoft.com/archive/blogs/schrimsher/counting-andor-identifying-unique-instances-of-things-in-powershell</link>
      <pubDate>Mon, 11 Jul 2016 12:46:52 GMT</pubDate>
      <dc:creator><![CDATA[Chris Schrimsher]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/schrimsher/?p=35</guid>
      <description><![CDATA[Greetings!

While not technically related directly to Exchange or Office 365, this tip can be used...]]></description>
      <content:encoded><![CDATA[Greetings!

While not technically related directly to Exchange or Office 365, this tip can be used for any number of things, including those two.  Several years ago, in support of what was then called the ExRAP (Exchange Risk Assessment Program), I came up with a neat little trick to count things in PowerShell using something called a hash table.  A good friend of mine, Gary Siepser, <a href="https://blogs.technet.microsoft.com/gary/2009/09/23/counting-public-folder-subfolders/" target="_blank">did a good write up of that specific case</a> (counting how many subfolders existed in each public folder in the hierarchy) back in 2009.

Now, let's get the simplest case out of the way first before we make it harder.  :)  To simply count the number of things in a collection (and/or get Average, Max, and Min for numeric properties), pipe them to <a href="https://technet.microsoft.com/en-us/library/hh849965.aspx" target="_blank">Measure-Object</a>.  But that's not what this post is about...  If you're dealing with "pure" .NET or PowerShell objects and just want a quick and dirty way to get a count of things grouped by a certain property of the PowerShell object, there's a super simple way to do it: it's called <a href="https://technet.microsoft.com/en-us/library/hh849907.aspx" target="_blank">Group-Object</a>.  (This will be super familiar to any of you familiar with T-SQL and the 'GROUP BY' clause).  For example, to see how many files of various extensions are in my Downloads folder:
<blockquote>
<pre>PS C:\Users\Chris\Downloads&gt; dir | Group-Object Extension
Count Name
----- ----
   24 .pdf
   14 .zip
    4 .mp4
...
</pre>
</blockquote>
I only put the "Count" and "Name" columns here, but for each one, PowerShell handily gives you a collection of objects matching that criteria.  Other use cases come to mind pretty easily... { Get-Service | Group-Object StartType } to show how many services are configured for each startup type, { Get-Process | Group-Object ProcessName } to see how many instances of processes are running (think svchost, wmiprvse, or MicrosoftEdgeCP), etc.

This is all well and good for very simple scenarios.  But what if you need to do some calculations?  Or if you need to group by something that isn't a property of a well-formed PowerShell object? (We'll examine this case in detail in a moment...)  Hash tables to the rescue! Hash tables basically let you store a bunch of values together as a collection of sorts and index into it by name.  For example,
<blockquote>
<pre>PS C:\&gt; $NewHashTable = @{}  #This is how you create a new hash table
PS C:\&gt; $NewHashTable["42"] = "the answer to life the universe and everything"
PS C:\&gt; $NewHashTable["MyName"] = "Chris"
PS C:\&gt; $NewHashTable

Name   Value
----   -----
42     the answer to life the universe and everything
MyName Chris
</pre>
</blockquote>
Now, what does this have to do with counting, you might ask?  Well...  Since everything in PowerShell is an object, the values referenced at the keys (or "indexes") you define are strongly typed, therefore you can directly manipulate the results just like you would any other variable.  So...  I can do something like this:
<blockquote>
<pre>$count = @{}  #Create the hash table
foreach ($myObject in $myCollection)
{
    if ($count[$myObject.Whatever] -eq $null) # If this is the first time we've seen this [whatever],
                                              # meaning if the indexed value is $null...
    {
        $count[$myObject.Whatever] = 1;       # ... then we create an entry for this [whatever] and
                                              # set it to 1 (for the 1st time we've seen it).
    }
    else   # If it's not $null, that means we have seen it before, and the value there is how many times 
           # we've seen it...
    {
        $count[$myObject.Whatever]++;  # ... so since we're seeing it again, we just increment it.
    }
}</pre>
</blockquote>
Now in this example, it would certainly have been simpler just to write { $myCollection | Group-Object Whatever } which would do the <em>exact</em> same thing.  But sometimes it's not that easy, and again, those cases aren't the primary purpose of this post.  For example, one of the things I use this for most frequently is looking for certain things in log files.  If, for example, I need to know a list of unique client IP addresses or how many times each URL was hit in a given IIS log file, I can't use Import-Csv and Group-Object because of the way the file/field headers are stored (the first few lines start with #, and the field headers aren't until line 4).  But, I <strong>can:</strong>
<ol>
	<li>Pull the log file into a variable using Get-Content</li>
	<li>Loop through the lines of the file with foreach</li>
	<li>Split each line by commas and store that line's "fields" in an array</li>
	<li>Index into that array by column number to retrieve the values I want from a given column</li>
	<li>Using those values to index into my hash table.</li>
</ol>
So, modifying my above example for an IIS log file:
<blockquote>
<pre>$uniqueIPs = @{}    #Create the hash table
$logFileContents = Get-Content E:\iis_logs\u_20160711.log   #Read the log file
$columnNum = 5 #I'm making this up for this example, but let's assume what I want is in the 6th column
               #No, that's not a typo -- indexes are 0 based so the 1st column is index 0, so the 6th column is index 5.  :)

foreach ($line in $logFileContents)
{
    $lineFields = $line.Split(",");
    $interestingValue = $lineFields[ $columnNum ];
    if ($uniqueIPs[ $interestingValue ] -eq $null) 
    {
        $uniqueIPs[ $interestingValue  ] = 1; 
    }
    else
    {
        $uniqueIPs[ $interestingValue ]]++;  
    }
}</pre>
</blockquote>
Assuming the client IP address (or URI query stem, or HTTP response code, or whatever I'm looking for) is actually in the 6th column, the hash table will now give me both a list of all unique values -- which sometimes is all I care about, and a count of how many times each value occurred -- which may or may not be useful, but hey, it's "free".  So the contents of my hash table might look something like:
<blockquote>
<pre>Name        Value
----        -----
1.1.1.1     3,456
2.2.2.2     4,567
</pre>
</blockquote>
Want to make it even more interesting?  Say I'm looking at SMTP Protocol Logs (which I do a LOT to get a list of all unique IPs that are using a Receive connector), where the client IP and port number are in a single field (e.g. "1.2.3.4:5678") but I don't care about port number.  Since I'm running my own code to evaluate each line, no biggie.  I would just change this line:
<blockquote>
<pre>$interestingValue = $lineFields[ $columnNum ];</pre>
</blockquote>
into something like this:
<blockquote>
<pre>$interestingValue = $lineFields[ $columnNum ];
$interestingValue = $interestingValue.Split(":")[0];</pre>
</blockquote>
This, of course, is horrible PowerShell form because there's no error checking etc., but essentially here's what we're doing.  $interestingValue = $lineFields[$columnNum] indexes into $lineFields at $columnNum -- in my case, 5 --which gets the 6th value since it's a zero-based array array containing all of the comma separated values on the line, and stores that in $interestingValue.  Then, we're telling PowerShell to split $interestingValue by ":" and take the first result (e.g. before the ":", which in this example would be IP address).

Now, to address the elephant in the room, I'm sure some of you out there are also thinking "Dude, why not just use LogParser?"  And yes, LogParser is definitely a more elegant and powerful solution.  However, in my 10+ years as a PFE and almost never touching the same server twice, I learn to take the "lowest common denominator" approach.  I can't assume that LogParser will be installed, I'm certainly not going to install it on a customer's production server outside of change control, and even though it's on my laptop, I may or may not have network access, and even if I do, I may or may not be allowed to copy a customer's log file to my PC for analysis.  Also, I go back to the point of this post -- this technique is generic and can be adapted to pretty much any scenario and is ubiquitously available.

More tk...
Chris

* PS - I have a photography background, and in photojournalism, "more tk" is frequently short for "more to come".]]></content:encoded>
    </item>
    <item>
      <title>Enabling TLS 1.1 and 1.2 in Outlook on Windows 7</title>
      <link>https://docs.microsoft.com/archive/blogs/schrimsher/enabling-tls-1-1-and-1-2-in-outlook-on-windows-7</link>
      <pubDate>Fri, 08 Jul 2016 10:53:46 GMT</pubDate>
      <dc:creator><![CDATA[Chris Schrimsher]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/schrimsher/?p=65</guid>
      <description><![CDATA[Happy Friday everyone!

I was recently on site with a customer in the financial services industry,...]]></description>
      <content:encoded><![CDATA[Happy Friday everyone!

I was recently on site with a customer in the financial services industry, and as any of you familiar with PCI DSS probably already know, there has been talk of disabling TLS 1.0 for quite some time.  The original deadline was June 30, 2016, but this has been extended until June 30, 2018.  For those of you not involved in PCI, there is still t<a target="_blank" href="https://en.wikipedia.org/wiki/Transport_Layer_Security#BEAST_attack" rel="noopener">he BEAST attack against TLS 1.0</a>.  :-)

Working with this customer in support of a hardware load balancer deployment, their Outlook clients (OL2013 on Windows 7) could not connect to Exchange (EX2013 on Windows 2012 R2) through the load balancer (F5 LTM).  Autodiscover and Outlook Anywhere were both broken.  However, accessing the Exchange load balancer URLs (/owa and /autodiscover/autodiscover.xml) via Internet Explorer on the same Windows 7 clients worked fine, and Outlook on a test Windows 10 VM also worked just fine.

We fired up Fiddler on the Win7 client and noticed that the Outlook connection was attempting to use TLS 1.0 (which was odd, since Windows 7 supports TLS 1.1 and 1.2), and that Schannel was returning error 0x80090326 (SEC_E_ILLEGAL_MESSAGE).  This Schannel error <a target="_blank" href="https://msdn.microsoft.com/en-us/library/windows/desktop/dd721886(v=vs.85).aspx" rel="noopener">maps to several TLS protocol alerts</a>, so we fired up Wireshark and noticed TLS alert 0x40, which is SSL3_ALERT_HANDSHAKE_FAILURE (don't be alarmed, the "SSL3" reference here is just a <a target="_blank" href="https://en.wikipedia.org/wiki/Red_herring" rel="noopener">red herring</a>).  Which means the "server" (the F5 in this case) couldn't accept some combination of options the client was proposing -- TLS protocol version, cipher suites, etc.

Looking at the Internet Explorer traffic (which worked), we noticed that it was offering TLS 1.2.  The Outlook traffic on the Win10 PC (which worked) was also offering TLS 1.2 (remember, Outlook on Win7 was only offering TLS 1.0).  Now we were getting somewhere...  We checked with the load balancer administrators and they confirmed that they had proactively disabled TLS 1.0 to be "ahead of the curve" with regard to PCI DSS requirements.  This was harmless since, in their minds, "All of our client OSes support TLS 1.1 and TLS 1.2."  And well, they weren't wrong.  :)

So what gives?  Well, I'll spare you the anguish that ensued (including setting Schannel registry keys like DisabledByDefault to 0 and Enabled to 1 for TLS 1.1 and 1.2 Client keys), but I ultimately found the referenced articles at the end of this post.  In summary, Office applications, including Outlook, use something called WinHTTP ("Windows HTTP Services").  Although Windows 7 (via Schannel) supports TLS 1.1 and 1.2, WinHTTP (and therefore applications built on WinHTTP) only support TLS 1.0.  The fix for this resides in <a target="_blank" href="https://support.microsoft.com/en-us/kb/3140245" rel="noopener">KB3140245</a>, released in March 2016.  Quoting the KB,
<blockquote>"This update adds support for DefaultSecureProtocols registry entry that allows the system administrator to specify which SSL protocols should be used when the WINHTTP_OPTION_SECURE_PROTOCOLS flag is used.

"This can allow certain applications that were built to use the WinHTTP default flag to be able to leverage the newer TLS 1.2 or TLS 1.1 protocols natively without any need for updates to the application."</blockquote>
So, in summary, here are the steps to enable Outlook on Windows 7 and Windows 8.0 to use TLS 1.1 and 1.2 to communicate with Exchange (the same goes for other apps, i.e. Word, and other servers, i.e. SharePoint):
<ol>
 	<li>Determine which TLS versions you want to enable, and determine the corresponding value for DefaultSecureProtocols (which we will add shortly):
<ol>
 	<li>For only TLS 1.1 and 1.2, the value will be 0xA00</li>
 	<li>For TLS 1.0, 1.1, and 1.2, the value will be 0xA80</li>
</ol>
</li>
 	<li>Install the KB3140245 update, either via Windows Update -- it's available as an Optional Update, or obtain via<a target="_blank" href="https://catalog.update.microsoft.com/" rel="noopener"> the Microsoft Update Catalog</a> and deploy as you would any other updates (SCCM, etc.).</li>
 	<li>Create a DWORD value called DefaultSecureProtocols in both of the following locations and set its value to the value determined in Step 1:
<ol>
 	<li>HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\WinHttp</li>
 	<li>HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Internet Settings\WinHttp</li>
</ol>
</li>
 	<li>EDIT: Thanks to Ivan's comment below, I'm adding this step.  Per the <a href="https://technet.microsoft.com/en-us/library/dn786418(v=ws.11).aspx">TLS-SSL Settings TechNet article</a>, be sure to create the DisabledByDefault DWORD value and set it to 0 in the following locations:
<ol>
 	<li>HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.1\Client</li>
 	<li>HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client</li>
</ol>
</li>
</ol>
Reboot and you're good to go!  Here are some articles for reference:
<ul>
 	<li><a target="_blank" href="https://blogs.technet.microsoft.com/office_integration__sharepoint/2015/04/20/office-2013-error-certificate-error-the-application-experienced-an-internal-error-loading-the-ssl-libraries-when-opening-files/" rel="noopener">Office 2013 error "Certificate error: The Application Experienced an Internal Error Loading the SSL Libraries" when opening files</a></li>
 	<li><a target="_blank" href="https://support.microsoft.com/en-us/kb/3140245" rel="noopener">Update to enable TLS 1.1 and TLS 1.2 as a default secure protocols in WinHTTP in Windows</a></li>
</ul>
And some random notes:
<ul>
 	<li>This behavior only affects Windows 7 and Windows 8.0:
<ul>
 	<li>Windows Vista didn't include support for TLS 1.1 and 1.2 at all.</li>
 	<li>Windows 8.1 and Windows 10 enable TLS 1.1 and 1.2 for WinHTTP-based applications by default.</li>
 	<li>Windows 7 and Windows 8.0 support TLS 1.1 and 1.2 via Schannel (hence why IE is able to use TLS 1.1 and 1.2) but do not enable TLS 1.1 and 1.2 for WinHTTP-based applications without the aforementioned update and registry values.  Simple, right?  ;-)</li>
</ul>
</li>
</ul>
One last note.  Although this update makes it possible for Outlook clients to use higher versions of TLS, at this time Microsoft does NOT recommend attempting to disable TLS 1.0 on Exchange servers themselves.  Please see <a target="_blank" href="https://blogs.technet.microsoft.com/exchange/2015/07/27/exchange-tls-ssl-best-practices/" rel="noopener">this article</a> for more details.

More tk...
Chris]]></content:encoded>
    </item>
    <item>
      <title>Welcome!</title>
      <link>https://docs.microsoft.com/archive/blogs/schrimsher/welcome</link>
      <pubDate>Thu, 07 Jul 2016 13:50:50 GMT</pubDate>
      <dc:creator><![CDATA[Chris Schrimsher]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/schrimsher/?p=25</guid>
      <description><![CDATA[Welcome everyone!

I've been with Microsoft for over 10 years (the majority of that time as a PFE...]]></description>
      <content:encoded><![CDATA[Welcome everyone!

I've been with Microsoft for over 10 years (the majority of that time as a PFE -- Premier Field Engineer), and have come close to starting my own blog on numerous occasions, but never took the plunge until now.  So, let me officially welcome you to my blog!

My intent with this blog is to publish things that I found interesting and/or helpful, specifically those things that I either a) haven't seen elsewhere or b) not applied to my particular scenario, in hopes of making relevant information easier for administrators to find.

For example, my "first" post (this is technically my first post, but my first technical post) will be regarding enabling TLS 1.1 / 1.2 connections to Exchange Server in Outlook running on Windows 7.  Although TLS 1.1 and 1.2 are fully supported by Schannel in Windows 7, it turns out that applications using WinHTTP ("Microsoft Windows HTTP Services"), such as Office (which includes Outlook), will only use TLS 1.0 by default.  It took me a while (and help from colleagues) to figure out that it takes an Optional Windows Update (published in March 2016) and the addition of a registry key to enable TLS 1.1 and 1.2 connections from these applications.

Thanks so much for your time, and I hope my future posts are helpful!

Sincerely,
Chris Schrimsher

&nbsp;

&nbsp;

&nbsp;]]></content:encoded>
    </item>
  </channel>
</rss>