Novell Home

Testing for Supported Cryptographic Functions

Novell Cool Solutions: Feature
By Aaron Burgemeister

Digg This - Slashdot This

Posted: 17 Oct 2007
 

Recently when learning about Novell Access Manager, I found a need to determine which cryptographic technologies the servers I hit would support. Normally, an SSL handshake takes place after the TCP handshake completes. The SSL client sends a list of its supported cryptographic functions, and the server chooses the strongest and responds letting the client know it can use that one. The start of the handshake makes seeing the client's supported functions easy to see in a LAN trace. However, there isn't an easy way to find out what the server supports, without getting the certificates from that machine and looking at them. This led to this tool.

This script is made to loop through all of the supported cryptos in openssl and then to test those against a given server:port. For example:

./findCrytoSupport.pl 123.45.67.89:443

The output shows the crypto name and whether or not it is supported. If you want ONLY the supported versions, then use an inverse grep on the word 'not' - like the following:

./findCryptoSupport.pl 123.45.67.89:443 | grep -v NOT

The limitation here is that openssl libraries on your machine may not have all of the cryptos available that the server supports. I haven't hit that problem yet, but it is a possibility, especially with really old versions of openssl and new servers.

Also as a note, I've always had the failure code include the $errorString variable's contents below. If other errors apply, more checks will be needed to check for those (add onto the current alternation regular expression). It may be worth modifying the check to not specifically look for error messages but instead to look for the size of the output. A returned size of only two lines indicates an error, while a return of dozens of lines indicates a success. I opted out of this, mainly because I didn't have time to test everything properly, and this was a thirty-minute solution to fill a quick need and to satisfy my curiosity about its feasibility.

As the script runs, it outputs a message saying which function on which server is being tested. This is all written to STDERR - redirecting it away should be trivial ('2>/dev/null' at the end of the command), leaving only the STDOUT behind for analysis.

Script

#!/usr/bin/perl
#Author: Aaron Burgemeister
#Version: 0.3.20071016220200
#
#This script is made to loop through all of the supported cryptos in openssl
#and then to test those against a given server:port. For example:
#./findCrytoSupport.pl 123.45.67.89:443
#
#The output shows the crypto name and whether or not it is supported.
#If you want ONLY the supported versions use an inverse grep on the word 'not'
#like the following:
#
#./findCryptoSupport.pl 123.45.67.89:443 | grep -v NOT
#
#The limitation here is that openssl libraries on your machine may not have
#all of the cryptos available that the server supports. I haven't hit that
#problem yet but it is a possibility, especially with really old versions
#of openssl and new servers.
#
#Also as a note I've always had the failure code include the $errorString
#variable's contents below. If other errors apply more checks will be
#needed to check for those (add onto the current alternation regular expression).
#It may be worth modifying the check to not specifically look for error
#messages but instead to look for the size of the output. A returned size
#of only two lines indicates an error while a return of dozens of lines
#indicates a success. I opted out of this mainly because I didn't have time
#to test everything properly and this was a thirty-minute solution to
#fill a quick need and to satisfy my curiosity about its feasibility.
#
#As the script runs it outputs a message saying which function on which server
#is being tested. This is all written to STDERR to redirecting it away should
#be trivial ('2>/dev/null' at the end of the command) leaving only the STDOUT
#behind for analysis.

my($serverString) = join(' ', @ARGV);
my(@servers) = split(/\s/, $serverString);
my($cmd0) = '';
my($result0) = '';
my(@ciphers) = ();
my($cipher0) = '';
my($server0) = '';
my($errorString) = 'sslv3 alert handshake failure|unknown protocol';
my(@finalGoodStuff) = ();

#Verify something was given as a parameter.
if(scalar(@servers) == 0)
{
 print "\n" . 'Usage: ' . $0 . ' server:port [server:port]...' . "\n";
 print 'Example: ' . $0 . ' www.google.com:443' . "\n";
 print '     ' . $0 . ' 123.45.67.89:636 www.novell.com:443 my.server:8443' . "\n\n";
 exit;
}#End if

$cmd0 = 'openssl ciphers';
$result0 = `$cmd0`;
chomp($result0);

#Get the ciphers into an array.
@ciphers = split(/:/, $result0);

#Loop through servers/ports (sockets).
foreach $server0 (@servers)
{
 push(@finalGoodStuff, 'Server: ' . $server0);
 print STDERR 'Server: ' . $server0 . "\n";
 #Loop through ciphers to see what the server supports.
 foreach $cipher0 (@ciphers)
 {
  print STDERR ' Testing crypto: ' . $cipher0 . "\n";
  $cmd0 = 'echo quit | openssl s_client -connect ' . $server0 . ' -cipher ' . $cipher0;

  #Run the command redirecting STDERR to STDOUT since most of the worthwhile output
  #is actually going to STDERR (only 'CONNECTED' line goes to STDOUT).
  $result0 = `$cmd0 2>&1`;
  if(($result0 =~ /CONNECTED/ ) && ($result0 !~ /$errorString/))
  {
   push(@finalGoodStuff, ' ' . $cipher0 . ' is supported.');
  }#End if
  elsif($result0 =~ /$errorString/)
  {
   push(@finalGoodStuff, ' ' . $cipher0 . ' is NOT supported. :-)');
  }#End elsif
  else
  {
   push(@finalGoodStuff, ' Failed connection to server; skipping...');
   last;
  }#End else
 }#End foreach
}#End foreach

#Print results.
print "\n\nResults:\n";
foreach $cipher0 (@finalGoodStuff)
{
 print $cipher0 . "\n";
}#End foreach
print "\n";

exit 0;


Novell Cool Solutions (corporate web communities) are produced by WebWise Solutions. www.webwiseone.com

© 2014 Novell