Exchange Server 2007 – troubleshooting SSL

Some points to troubleshoot an Exchange Server 2007 SSL configuration. For god knows what reason, Microsoft decided that everything needed to be command line, so it’s pretty easy to get stuck.

Starting point – find what certificates are installed

Run the following cmdlet from the Exchange Shell:

Get-ExchangeCertificate

You should see output similar to:

Thumbprint                Services Subject
----------                -------- -------
1B5667CCB803BC4AD13E7E51A .IP.W    CN=mail.example.com....
103F3F32814A48D2416ECC5DB S....    CN=exch-07
43C6A1548782A25ABA425B471 ....W    CN=exch-07.example....

The Thumbprint is the identifier used in other cmdlets when referring to a specific certificate. The Services are what the certificate is enabled for; each letter indicates what service(s) are configured:

LetterService
SSMTP – outbound e-mail secured with TLS
IIMAP – inbound e-mail
PPOP3 – inbound e-mail
UUnified Messaging – I believe this is for Outlook Anywhere
WOutlook Web Access / IIS – webmail

You can also get more detailed information about a specific certificate with the following command:

Get-ExchangeCertificate [thumbprint] | fl

Are the certificates enabled for the right things? Are multiple certificates enabled for the same service (as per the example above)? Is the right certificate installed at all? Has the certificate expired? Does the certificate have incorrect or misspelt details in the DN? Etc..

Handy commands:

Turn a specific service on (Outlook Web Access in this example):

Enable-ExchangeCertificate -Thumbprint [thumbprint] -Services IIS

Disable a certificate:

Enable-ExchangeCertificate -Thumbprint [thumbprint] -Services None

Remove a certificate:
This command does what it says on the tin – there is no undo!

Remove-ExchangeCertificate -Thumbprint [thumbprint]

Aside from using the above to fix obvious problems, the Event Viewer contains very useful error codes and explanatory messages in well-formed English (which is just about a first for any Microsoft product, I think). Combination that + Google will provide fixes for most problems.

One thing I’ve seen once or twice is a certificate that the customer swears black-and-blue has been installed and it’s just not showing up in the Get-ExchangeCertificate output. If you look in (the Certificates snap-in in) MMC, it’s there. What’s happened? The customer requested the certificate in Exchange, but imported the certificate response in to MMC directly. Ergo, public and private keys not matched up and certificate not available to Exchange. Delete certificate from MMC, import in to Exchange instead.

Exporting certificates from a Java keystore

There is a patently easy way to convert JKS keystores to PKCS12 certificate bundles (and vice versa). It’s a (poorly documented) keytool command that was introduced with JDK 6:

Convert JKS to P12

keytool -importkeystore -srckeystore keystore.jks -srcstoretype JKS -deststoretype PKCS12 -destkeystore keystore.p12

Convert P12 to JKS

keytool -importkeystore -srckeystore keystore.p12 -srcstoretype PKCS12 -deststoretype JKS -destkeystore keystore.jks

Borrowed from a blog post by tomas at EJBCA.

Dynamic IP script for Internode

WWW::Mechanize script for programmatically obtaining the current (dynamic) IPv4 and IPv6 addresses assigned to an Internode ADSL session:

#!/usr/bin/perl

use strict;
use warnings;
use WWW::Mechanize;

## Get current session data for our Internode session

my $mech = WWW::Mechanize->new();
my $user = ""; ## Enter Internode username
my $pass = ""; ## Enter Internode password

$mech->get('https://secure.internode.on.net/myinternode/sys0/login');
$mech->form_number(2);
$mech->set_fields(username => $user, password => $pass);
$mech->click('action');
$mech->follow_link (url_regex => qr/currentsessions/);

my $output = $mech->text();

## Locate IPv4 address in output
## ('IPv4:' on one side, '(dynamic)' on the other side)

my $v4_left = index ($output, "IPv4:") + 5;
my $v4_right = index ($output, "\(dynamic\)");

## Move IPv4 address in to its' own variable
## Remove new lines, leading and trailing spaces

my $ipv4 = substr $output, $v4_left, ($v4_right - $v4_left);
chomp $ipv4;
$ipv4 =~ s/^\s+//;
$ipv4 =~ s/\s+$//;

## Now do the same for the dynamically-assigned IPv6 address
## ('IPv6:' on one side, '(dynamic)' on the other side)

my $v6_left = index ($output, "IPv6:") + 5;
my $v6_right = rindex ($output, "\(dynamic\)");

## Move IPv6 address in to its' own variable
## Remove new lines, leading and trailing spaces

my $ipv6 = substr $output, $v6_left, ($v6_right - $v6_left);
chomp $ipv6;
$ipv6 =~ s/^\s+//;
$ipv6 =~ s/\s+$//;

## Print output

print "$ipv4\n";
print "$ipv6\n";

exit;