Friday, May 31, 2013

PowerShell script to enhance the Windows CA SMTP exit module

Windows CA SMTP exit module

the Windows Certification Authority has a built in feature (Windows Enterprise SKU) to send out emails to inform the PKI administrators if a new pending certificate request waiting for approval or if a new certificate has been issued. Just 2 examples.

The configuration must be done in the registry: See here for an example
http://social.technet.microsoft.com/wiki/contents/articles/2004.active-directory-certificate-services-smtp-exit-module-for-windows-server-2008-r2-example.aspx

Unfortunately you cannot configure it to send the issued certificate to the certificate requestor. For that I wrote a PowerShell script what is also working with the Windows Server 2008 R2 Standard Server.

Config file - sendcert_inc.ps1:

$sendcertpath=".\sendcert"
$msgFrom='noreply@frontoso.com'
$smtphost='127.0.0.1'
$certtmpl="1.3.6.1.4.1.311.21.8.5245527.10310595.8014498.11013764.15833798.137.13192380.4508386" #CorpWebServer
$certfileExt="txt" # fyi: extensions cer and der are blocked by Outlook
$mailbody="mailbody.txt"
$dbscanperiod="03:00" # 01:00 = 1 day, 1:15 = 1 day 15 hours; $dbscanperiod is the max time (now - $dbscanperiod) sendcert goes back in the certificate database, e.g. useful if you have already issued certs for years and you going to enable sendcert now


Mailbody.txt

Hello, attached is the requested certificate.

Please download the certificate and proceed with the SSL/TLS setup of your application.

For your convenience the certificate can be found as attachment and in the mail body.


Thank you,


----------------------------------------------------------------------------
Do not reply to this message. It was sent from an unmonitored email account.




sendcert.ps1

#
# Author: lutz.mueller-hipper@tribaldi.net
# Updates: lutz.mueller-hipper@insight.com
# Date: May 23, 2013 - v3.1
#
clear

import-module ActiveDirectory
# if not yet installed please install the ActiveDirectory PowerShell module
#dism /online /enable-feature /featurename:ActiveDirectory-PowerShell

if (-not (Test-Path .\sendcert_inc.ps1))
{
  write-host "Error: sendcert_inc.ps1 configuration file not found." >>sendcert.log
  exit;
} else {
  . .\sendcert_inc.ps1
}

if (-not (Test-Path $sendcertpath)) { mkdir $sendcertpath >$null}

$Arr_SendCert = @()

write-host "=========================="
write-host Start Send certificate via email to certificate requestor
write-host "=========================="
write-host

#Disposition Description
#20 certificate was issued
#21 certificate is revoked
#30 certificate request failed
#31 certificate request is denied

$reqid_db = @()
$reqid_db = get-content $sendcertpath\reqid_do_not_remove.txt

$reqid_db2 = @()

foreach ( $line in $reqid_db) {
 write-host "Line: "$line
 $reqid_db2 = $reqid_db2 + $line
}

certutil.exe -view -out "Request.requestid,Request.requestid" -restrict "CertificateTemplate=$certtmpl,Disposition=20,NotBefore>now-$dbscanperiod" csv > $sendcertpath\sendcert_scope.csv
$collection = @(Import-CSV $sendcertpath\sendcert_scope.csv)
write-host Issued certs during period: $collection.count

if ($collection.count -gt 0) {
  foreach($CADBentry in $collection)
  {

    $reqid = $CADBentry."request id"

    if ($reqid_db2 -notcontains $reqid) {  
    write-host 'Preparing email for request: ' $reqid

    $certview = certutil.exe -view -out "rawcertificate" -restrict "Request.requestid=$reqid"

    $certemail = @()
    $certattach = @()
    foreach($line in $certview)
     {
     #write-host "Line: " $line

     if ( $line -eq "-----BEGIN CERTIFICATE-----" ) { $certbegin="1" }
     if ( $certbegin -eq "1") {
       #write-host "next person in line pls"
       $certemail = $certemail + $line.trim() + "`n" #+ "`r`n"
       $certattach = $certattach + $line.trim() # + "`n" #+ "`r`n"
     
     }
     if ( $line -eq "-----END CERTIFICATE-----" ) { $certbegin="0" }

    }
    $cadb_requser= certutil.exe -view -out "Requester Name" -restrict "Request.requestid=$reqid" csv
    $requser = $cadb_requser[1]
    $requser = $requser.split("\")
    $user = $requser[1]
    $requser = $user.split("`"")
    $user = $requser[0]

$aduser=""

try {
 $aduser = get-aduser $user -Properties mail
  #$aduser.mail
}

catch [Exception] {
   write-host $_.Exception.Message
}

if ($aduser.mail.length -lt 1) {
  write-host "no email address found"
} else {

    $certattach > $sendcertpath\$reqid"."$certfileExt

$msg=new-object System.Net.Mail.MailMessage
$msg.From=$msgFrom
$msg.to.Add($aduser.mail)
$msg.Subject=$env:computername + ": SSL certificate " + $reqid
$msg.IsBodyHtml=$false
$mailbody = @()
$getmailbody = Get-Content mailbody.txt
foreach ($line in $getmailbody) {
  $mailbody = $mailbody + $line + "`n"
}
$msg.Body=@"

$mailbody

$certemail

-
Ref $reqid_$env:computername

"@

$att = new-object Net.Mail.Attachment($sendcertpath + "\" + $reqid + "." + $certfileExt)
$msg.Attachments.Add($att)


$smtp=new-object System.Net.Mail.SmtpClient
$smtp.host=$smtphost

try {
  $smtp.Send($msg)
  $reqid >> $sendcertpath\reqid_do_not_remove.txt
}
catch {
 write-host $_.Exception.Message
}
finally {
  $smtp.dispose
  $att.dispose()
    }
   }
  }
 }
}


Friday, March 29, 2013

Cannot request a certificate and Error 1722: The RPC server is unavailable

RPC errors can be ugly and are often not that easy to identify. In the last months I had two Windows PKI Installations where I ran into the error 1722 RPC server not available. In both cases the Windows CA was up and running but I could not enroll or autoenroll certificates. So I check the firewall rules, the CA server time and date and I used certutil.exe -ping CAhostname to verify RPC network communication.

I ran certutil -ping one time with the netbios name of the CA and all worked. That's why no one had an issued with the machine before for file transfer or a ping with the netbios name.


C:\system\>certutil -ping win5011
Connecting to win5011 ...
Server "AAA Frontoso R3" ICertRequest2 interface is alive
CertUtil: -ping command completed successfully.


But the certutil -ping for the full qualified hostname failed.


C:\system\adhc>certutil -ping win5011.frontoso.com
Connecting to win5011.frontoso.com ...
Server could not be reached: The RPC server is unavailable. 0x800706ba (WIN32: 1722)

CertUtil: -ping command FAILED: 0x800706ba (WIN32: 1722)
CertUtil: The RPC server is unavailable.


So it turned out that in both cases the client used a non-MS DNS server for the Active Directory environment and the FQDN name of the CA server was incorrectly configured there. After adjusting the IP address in DNS certutil -ping with the FQDN name worked and the certificate enrollment as well.

Ease Your Life when using Openssl s_client

I am really a big fan of openssl for certificate and network communication troubleshooting. And I am using it most of time from a Windows system.
I use the openssl s_client command very often to verify the network connectivity to a web or application server and to troubleshoot certificate errors in applications.

Openssl s_client gives out a lot of valuable information, but for inspecting the certificate you have first to transfer it into the correct file format. That should be easier to do. :-)

Example: openssl s_client -connect www.google.com:443



Loading 'screen' into random state - done
CONNECTED(00000128)
depth=1 C = US, O = Google Inc, CN = Google Internet Authority
verify error:num=20:unable to get local issuer certificate
verify return:0
---
Certificate chain
 0 s:/C=US/ST=California/L=Mountain View/O=Google Inc/CN=www.google.com
   i:/C=US/O=Google Inc/CN=Google Internet Authority
 1 s:/C=US/O=Google Inc/CN=Google Internet Authority
   i:/C=US/O=Equifax/OU=Equifax Secure Certificate Authority
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIDgDCCAumgAwIBAgIKO6d8eAAAAACBeTANBgkqhkiG9w0BAQUFADBGMQswCQYD
VQQGEwJVUzETMBEGA1UEChMKR29vZ2xlIEluYzEiMCAGA1UEAxMZR29vZ2xlIElu
dGVybmV0IEF1dGhvcml0eTAeFw0xMzAzMTMxMzUyNDJaFw0xMzA2MDcxOTQzMjda
MGgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1N
b3VudGFpbiBWaWV3MRMwEQYDVQQKEwpHb29nbGUgSW5jMRcwFQYDVQQDEw53d3cu
Z29vZ2xlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAzhYmBbH1F/Es
0HQevxU1WnQ+08bGZS615oiYVxxl2D74Nf4WbQRuXs6iju+RLOFrNAKgOPtQ8DLw
zo/ln9yzzm1iXGQJa8lOScTMdTg/4UQAQjJ5F8fYZr8zAdQbur/BQ5YSiyVqLO0t
N3IeezSvYC9r5SwSMLmnEqXCIa5B8sECAwEAAaOCAVEwggFNMB0GA1UdJQQWMBQG
CCsGAQUFBwMBBggrBgEFBQcDAjAdBgNVHQ4EFgQUdfF5NV20rqEcyl3mVAxqB7bE
2JkwHwYDVR0jBBgwFoAUv8Aw6/VDET5nup6R+/xq2uNrEiQwWwYDVR0fBFQwUjBQ
oE6gTIZKaHR0cDovL3d3dy5nc3RhdGljLmNvbS9Hb29nbGVJbnRlcm5ldEF1dGhv
cml0eS9Hb29nbGVJbnRlcm5ldEF1dGhvcml0eS5jcmwwZgYIKwYBBQUHAQEEWjBY
MFYGCCsGAQUFBzAChkpodHRwOi8vd3d3LmdzdGF0aWMuY29tL0dvb2dsZUludGVy
bmV0QXV0aG9yaXR5L0dvb2dsZUludGVybmV0QXV0aG9yaXR5LmNydDAMBgNVHRMB
Af8EAjAAMBkGA1UdEQQSMBCCDnd3dy5nb29nbGUuY29tMA0GCSqGSIb3DQEBBQUA
A4GBAKD8fqndlHcfvIHSXo5R/ehNsRXkyinvxwG4r1oMuO60c1KRV0DB22Mvqjp5
vn4nnkYfiVoQv/LlsIBy48is9jKB5AYyPq5R3LSrn7iheYlGY1omSZkdmHDBLtcl
+TtjTtz444O+7dYZAM0GyUdf/3HUoebs949KIu2Cg5QS8INZ
-----END CERTIFICATE-----
subject=/C=US/ST=California/L=Mountain View/O=Google Inc/CN=www.google.com
issuer=/C=US/O=Google Inc/CN=Google Internet Authority
---
No client certificate CA names sent
---
SSL handshake has read 2103 bytes and written 332 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-RC4-SHA
Server public key is 1024 bit
Secure Renegotiation IS supported
Compression: NONE
[cut]

Information about the validity (start,end), the server certificate thumbprint are not displayed. In the past I copied the lines from BEGIN CERTIFICATE to END CERTIFICATE into a text file using Notepad and I saved the file as cert1.cer. Then I could double-click the file in Windows Explorer and I had a nice interface to search through all attributes. Last week I figured out a more convenient way to do that. You can redirect the entire openssl s_client output into a cert1.cer file and the Windows Certificate Wizard is smart enough to read just the certificate from all the result data.

openssl s_client -connect www.google.com:443 > cert1.cer

Now you have a nice looking graphical interface to go through all the certificate information.



Wednesday, January 9, 2013

Manipulating the Microsoft Deployment Toolkit (MDT) database using PowerShell

I am helping at the school of our children to run the Windows server and workstations. For this and also in my lab I setup MDT to deploy new physical or virtual machines.
At school we buy used/re-furbished desktop or laptop computers a lot and all of them come with a unique Windows license. And we just cannot afford to buy a additional Enterprise license for each.
So MDT helps us also to keep track of all Windows product keys and we put them one time in a spreadsheet (we get some help from students here). So end of 2012 we got 35 new machines and I thought it would be nice to import the spreadsheet into the MDT database and assign the role to install Windows 7 32bit to them as well.

So I found this post http://blogs.technet.com/b/mniehaus/archive/2009/05/15/manipulating-the-microsoft-deployment-toolkit-database-using-powershell.aspx from Michael Niehaus and I downloaded the PowerShell command lets he provided as well.

Our spreadsheet has the format:
- 1. line includes the data headers: computername, Windows product code, machine's serial number
- the other lines have the data
The spreadsheet is delimited by tabs.

And her is the PowerShell I created:

##########


# Import the CSV file into a PowerShell array
$collection = @(Import-CSV .\HPlabcomputers20121231.csv -Delimiter "`t")

# Connect to the SQL database
connect-mdtdatabase -sqlserver . -database MDTDB

# Create for each computer an entry in the MDT database
foreach($computer in $collection)
{
$PCNAME=$computer.ComputerName
$SerialNum=$computer.SerialNum
$ProdKey=$computer.WinProductKey
write-host Importing $PCNAME
new-mdtcomputer -assetTag $computer.ComputerName -serialNumber $SerialNum -settings @{OSInstall='YES'; OSDComputerName=$PCNAME; ProductKey=$ProdKey}
}

# Assign for each computer the role to install Win7 Pro 32 bit
foreach($computer in $collection)
{
$PCNAME=$computer.ComputerName
write-host Updating $PCNAME
# Search for the computername and set the computer role
get-mdtcomputer -assetTag $PCNAME | Set-MDTComputerRole -roles @('Win7_lab_computers')
}


##########

So obviously the user account you use must have SQL permissions on the MDT database to update the database.
Also note that the MDT MMC (aka Deployment Workbench) does not show the new computers if you just click refresh on the Computers view under MDT Deployment Share/Advanced Configuration/Database. Click instead on Database and hit refresh, and go back to the Computers view.






Tuesday, December 4, 2012

Certificate Autoenrollment and RDS cause a certificate flood

All,

I love using machine certificates for RDP SSL as well. This week I came across an issue where I first thought autoenrollment is freaking out and generates on every reboot or gpupdate /force a new certificate.

After I found tons of articles why autoenrollment is not working at all but nothing about issuing to many certificates. I luckily found an article about the GPO settings for RDP.

http://social.technet.microsoft.com/Forums/en-US/winserverTS/thread/382774a9-5b2c-4d54-9abb-03357adccc08

RDP GPO settings http://technet.microsoft.com/en-us/library/cc771869(WS.10).aspx

So it seems that this "known" issue is not yet fixed. Or perhaps it is and I just do not know the KB article number.

Solution in short: Keep "Template Display Name" and "Template Name" with the exact same spelling and no spaces. See below.





Thursday, October 25, 2012

New study about Validating SSL Certificates in Non-Browser Software


Scientist from The University of Texas and the Stanford University have published a study about SSL encryption in several products and services.
Even applications using data encryption they do not perform an proper identity verification of the sender or receiver. I have seen this before for online backup services, password sync tools etc.
So that is not a new thing, but it is amazing that we still have to deal with that.

Read the article http://www.cs.utexas.edu/~shmat/shmat_ccs12.pdf

Thursday, October 11, 2012

1-2-3 : See what is in a SAML response



1. Get Fiddler 2 installed http://www.fiddler2.com/fiddler2/version.asp, downlaod  and active HTTPS inspection (HTTPS inspection can break the communication for some services when it is activated, e.g. Outlook using RPC over HTTP)

2. Download XML Notepad from here http://www.microsoft.com/en-us/download/details.aspx?displaylang=en&id=7973


3. Start Fiddler, hit F8 to see the Inspectors

4. Log on to your SaaS application

5. Go back to Fiddler. Click on the first entry in Web Sessions what is hiting the SaaS vendor, click on Inspectors and RAW on the right hand side. Copy the SAMLresponse from the RAW tab to https://rnd.feide.no/simplesaml/module.php/saml2debug/debug.php

and click on "Decode"

6. Copy the decoded  SAMLresponse to the clipboard.

7. Open XML notepad and hit CTRL-V.