Advertisement
Guest User

SSLscan.c

a guest
Mar 2nd, 2015
603
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 75.69 KB | None | 0 0
  1. /***************************************************************************
  2.  *   sslscan - A SSL cipher scanning tool                                  *
  3.  *   Copyright 2007-2010 by Ian Ventura-Whiting (fizz@titania.co.uk)       *
  4.  *                          Michael Boman (michael@michaelboman.org)       *
  5.  *                                                                         *
  6.  *   This program is free software; you can redistribute it and/or modify  *
  7.  *   it under the terms of the GNU General Public License as published by  *
  8.  *   the Free Software Foundation; either version 3 of the License, or     *
  9.  *   (at your option) any later version.                                   *
  10.  *                                                                         *
  11.  *   This program is distributed in the hope that it will be useful,       *
  12.  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
  13.  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
  14.  *   GNU General Public License for more details.                          *
  15.  *                                                                         *
  16.  *   You should have received a copy of the GNU General Public License     *
  17.  *   along with this program. If not, see <http://www.gnu.org/licenses/>.  *
  18.  *                                                                         *
  19.  *   In addition, as a special exception, the copyright holders give       *
  20.  *   permission to link the code of portions of this program with the      *
  21.  *   OpenSSL library under certain conditions as described in each         *
  22.  *   individual source file, and distribute linked combinations            *
  23.  *   including the two.                                                    *
  24.  *   You must obey the GNU General Public License in all respects          *
  25.  *   for all of the code used other than OpenSSL.  If you modify           *
  26.  *   file(s) with this exception, you may extend this exception to your    *
  27.  *   version of the file(s), but you are not obligated to do so.  If you   *
  28.  *   do not wish to do so, delete this exception statement from your       *
  29.  *   version.  If you delete this exception statement from all source      *
  30.  *   files in the program, then also delete it here.                       *
  31.  ***************************************************************************/
  32.  
  33. // Includes...
  34. #include <string.h>
  35. #if defined(WIN32)
  36. #include <stdio.h>
  37. #include <winsock2.h>
  38. #include <windows.h>
  39. #include <ws2tcpip.h>
  40. #define snprintf(...) _snprintf(__VA_ARGS__)
  41. DWORD dwError;
  42. #else
  43. #include <netdb.h>
  44. #include <unistd.h>
  45. #include <sys/socket.h>
  46. #include <fcntl.h>
  47. #endif
  48. #include <sys/stat.h>
  49. #include <time.h>
  50.  
  51. // OpenSSL Include files
  52. #include <openssl/err.h>
  53. #include <openssl/ssl.h>
  54. #include <openssl/pkcs12.h>
  55. #include <openssl/x509.h>
  56. #include <openssl/x509v3.h>
  57.  
  58. #if defined(WIN32)
  59. #include <openssl/applink.c>
  60. #endif
  61.  
  62. // Defines...
  63. #define false 0
  64. #define true 1
  65.  
  66. #define mode_help 0
  67. #define mode_version 1
  68. #define mode_single 2
  69. #define mode_multiple 3
  70.  
  71. #define BUFFERSIZE 1024
  72.  
  73. #define ssl_all 0
  74. #define ssl_v2 1
  75. #define ssl_v3 2
  76. #define tls_v1 3
  77.  
  78. // Macros
  79. #define MAXSTRLEN(x) sizeof(x) - 1
  80. #define FREEIFNOTNULL(x) if (x != NULL) free(x)
  81. #if defined (WIN32)
  82. // In MS World close(s) is called closesocket(s)
  83. #define CLOSESOCKET(s) closesocket(s)
  84. // In MS World snprintf() is called _snprintf()
  85. #define snprintf(...) _snprintf(__VA_ARGS__)
  86. #else
  87. #define CLOSESOCKET(s) close(s)
  88. #endif
  89.  
  90. #if ( OPENSSL_VERSION_NUMBER > 0x009080cfL )
  91. #define _GET_SECURE_RENEGOTIATION
  92. #endif
  93.  
  94. #define CIPHER_MASK   "ALL:COMPLEMENTOFALL" // :@STRENGTH"
  95.  
  96. // Version numbers and banners
  97. #define SSLSCAN_VERSION "1.9.2-win32"
  98. const char *program_banner = "                   _\n"
  99.                              "           ___ ___| |___  ___ __ _ _ __\n"
  100.                              "          / __/ __| / __|/ __/ _` | '_ \\\n"
  101.                              "          \\__ \\__ \\ \\__ \\ (_| (_| | | | |\n"
  102.                              "          |___/___/_|___/\\___\\__,_|_| |_|\n\n"
  103.                              "                  Version " SSLSCAN_VERSION "\n"
  104.                              "             http://www.titania.co.uk\n"
  105.                              " Copyright 2010 Ian Ventura-Whiting / Michael Boman\n"
  106.                              "    Compiled against " OPENSSL_VERSION_TEXT "\n";
  107. const char *program_version = "sslscan version " SSLSCAN_VERSION "\n" OPENSSL_VERSION_TEXT "\nhttp://www.titania.co.uk\nCopyright (C) Ian Ventura-Whiting 2009\n";
  108. const char *xml_version = SSLSCAN_VERSION;
  109.  
  110.  
  111.  
  112. struct certificateOutput
  113. {
  114.     long version;
  115.     long serial;
  116.     char signatureAlgorithm[BUFFERSIZE];
  117.     char issuer[BUFFERSIZE];
  118.     char *notValidBefore;
  119.     char *notValidAfter;
  120.     char subject[BUFFERSIZE];
  121.     char pkAlgorithm[BUFFERSIZE];
  122.     char *pk;
  123.     char pkType[BUFFERSIZE];
  124.     int  pkError;
  125.     int  pkBits;
  126.     int verifyError;
  127.     char verifyErrorString[BUFFERSIZE];
  128.     struct certificateExtensionOutput *firstCertExt;
  129. };
  130.  
  131. struct certificateExtensionOutput
  132. {
  133.     char *name;
  134.     int  critical;
  135.     char *data;
  136.     struct certificateExtensionOutput *next;
  137. };
  138.  
  139. struct renegotiationOutput
  140. {
  141.     int supported;
  142.     int secure;
  143. };
  144.  
  145. struct cipherOutput
  146. {
  147.     char status[BUFFERSIZE];
  148.     char sslVersion[BUFFERSIZE];
  149.     char cipherName[BUFFERSIZE];
  150.     int  cipherBits;
  151.     char cipherKx[BUFFERSIZE];
  152.     char cipherAu[BUFFERSIZE];
  153.     char cipherEnc[BUFFERSIZE];
  154.     char cipherMac[BUFFERSIZE];
  155.     char L4String[BUFFERSIZE];
  156. };
  157.  
  158. struct sslCipher
  159. {
  160.     // Cipher Properties...
  161.     const char *name;
  162.     char *version;
  163.     int bits;
  164.     char description[512];
  165.     SSL_METHOD *sslMethod;
  166.     struct sslCipher *next;
  167. };
  168.  
  169. struct sslCheckOptions
  170. {
  171.     // Program Options...
  172.     char host[512];
  173.     int port;
  174.     int noFailed;
  175.     int starttls;
  176.     int sslVersion;
  177.     int targets;
  178.     int pout;
  179.     int sslbugs;
  180.     int http;
  181.     int quiet;
  182.  
  183.     // File Handles...
  184.     FILE *xmlOutput;
  185.  
  186.     // TCP Connection Variables...
  187.     struct hostent *hostStruct;
  188.     struct sockaddr_in serverAddress;
  189.  
  190.     // SSL Variables...
  191.     SSL_CTX *ctx;
  192.     struct sslCipher *ciphers;
  193.     char *clientCertsFile;
  194.     char *privateKeyFile;
  195.     char *privateKeyPassword;
  196.  
  197.     // CA variables...
  198.     char *CAfile;
  199.     char *CApath;
  200. };
  201.  
  202. #if defined (WIN32)
  203. char *strndup(char *str, int n)
  204. {
  205.     char *buffer;
  206.     char *startptr;
  207.  
  208.     buffer = malloc(n + 1);
  209.     startptr = buffer;
  210.     while (n && *str)
  211.     {
  212.         *buffer = *str;
  213.         buffer++;
  214.         str++;
  215.         n--;
  216.     }
  217.     *buffer = '\0';
  218.     return (startptr);
  219. }
  220. #endif
  221.  
  222. #if defined (WIN32)
  223. void setConnectionTimeout( int hSocket, DWORD timeout )
  224. {
  225.     setsockopt(hSocket,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof timeout);
  226.     setsockopt(hSocket,SOL_SOCKET,SO_SNDTIMEO,(char*)&timeout,sizeof timeout);
  227. }
  228. #else
  229. void setConnectionTimeout( int hSocket, int timeout )
  230. {
  231.     struct timeval tv;
  232.     tv.tv_sec = timeout/1000;
  233.     tv.tv_usec = 0;
  234.  
  235.     setsockopt(hSocket,SOL_SOCKET,SO_RCVTIMEO,(char*)&tv, sizeof(tv));
  236.     setsockopt(hSocket,SOL_SOCKET,SO_SNDTIMEO,(char*)&tv, sizeof(tv));
  237. }
  238. #endif
  239.  
  240. int outputRenegotiaition( struct sslCheckOptions *options, struct renegotiationOutput *outputData)
  241. {
  242.     if (options->quiet == false)
  243.     {
  244.         if (outputData->secure)
  245.             printf("Secure session renegotiations supported\n");
  246.         else if (outputData->supported)
  247.             printf("Insecure session renegotiations supported\n");
  248.         else
  249.             printf("Session renegotiation not supported\n");
  250.     }
  251.  
  252.     if (options->xmlOutput != 0)
  253.     {
  254.         printf("  <renegotiation supported=\"%d\" secure=\"%d\" />\n",
  255.             outputData->supported,
  256.             outputData->secure);
  257.     }
  258.     return true;
  259. }
  260.  
  261. int outputCertExtensions( struct sslCheckOptions *options, struct certificateExtensionOutput *outputData )
  262. {
  263.     struct certificateExtensionOutput *outputDataPtr;
  264.     outputDataPtr = outputData;
  265.  
  266.     while( outputDataPtr != NULL )
  267.     {
  268. #if 0 == 1
  269.         printf("DEBUG: name=%s\tcritical=%s\tdata=%s\n",
  270.             outputDataPtr->name,
  271.             outputDataPtr->critical ? "critical":"",
  272.             outputDataPtr->data);
  273. #endif
  274.         if (options->quiet == false)
  275.         {
  276.             if (NULL != outputDataPtr->name) {
  277.               printf("%s: %s\n", outputDataPtr->name, outputDataPtr->critical ? "critical":"");
  278.               printf("%s\n", outputDataPtr->data);
  279.             }
  280.         }
  281.  
  282.         if (options->pout)
  283.         {
  284.         }
  285.         outputDataPtr = outputDataPtr->next;
  286.     }
  287.  
  288.     return true;
  289. }
  290.  
  291. int outputCertExtensionsXML( struct sslCheckOptions *options, struct certificateExtensionOutput *outputData )
  292. {
  293.     if (options->xmlOutput != 0)
  294.     {
  295.         while( outputData != NULL )
  296.         {
  297.             if ((outputData->name != NULL) && (outputData->data != NULL ))
  298.             {
  299.                 fprintf(options->xmlOutput, "    <extension name=\"%s\"%s><![CDATA[%s]]></extension>\n",
  300.                     outputData->name,
  301.                     outputData->critical ? " level=\"critical\"":"",
  302.                     outputData->data);
  303.                 fflush(options->xmlOutput);
  304.             }
  305.             outputData = outputData->next;
  306.         }
  307.     }
  308.     return true;
  309. }
  310.  
  311. int outputCertificate( struct sslCheckOptions *options, struct certificateOutput *outputData )
  312. {
  313.     if ( !outputData->pkError )
  314.     {
  315.         if ( options->quiet == false )
  316.         {
  317.             printf("\n  SSL Certificate:\n");
  318.             printf("    Version: %l\n", outputData->version);
  319.             printf("    Serial Number: %u\n", outputData->serial);
  320.             printf("    Signature Algorithm: %s\n", outputData->signatureAlgorithm);
  321.             printf("    Issuer: %s\n", outputData->issuer);
  322.             printf("    Not valid before: %s\n", outputData->notValidBefore);
  323.             printf("    Not valid after: %s\n", outputData->notValidAfter);
  324.             printf("    Subject: %s\n", outputData->subject);
  325.             printf("    Public Key Algorithm: %s\n", outputData->pkAlgorithm);
  326.             printf("    %s Public Key: (%d bit):\n%s\n", outputData->pkAlgorithm, outputData->pkBits, outputData->pk);
  327.             outputCertExtensions(options, outputData->firstCertExt);
  328.         }
  329.  
  330.         if ( options->xmlOutput != 0 )
  331.         {
  332.             fprintf(options->xmlOutput, "  <certificate>\n");
  333.             fprintf(options->xmlOutput, "   <version>%d</version>\n", outputData->version);
  334.             fprintf(options->xmlOutput, "   <serial>%u</serial>\n", outputData->serial);
  335.             fprintf(options->xmlOutput, "   <signature-algorithm>%s</signature-algorithm>\n", outputData->signatureAlgorithm);
  336.             fprintf(options->xmlOutput, "   <issuer>%s</issuer>\n", outputData->issuer);
  337.             fprintf(options->xmlOutput, "   <not-valid-before>%s</not-valid-before>\n", outputData->notValidBefore);
  338.             fprintf(options->xmlOutput, "   <not-valid-after>%s</not-valid-after>\n", outputData->notValidAfter);
  339.             fprintf(options->xmlOutput, "   <subject>%s</subject>\n", outputData->subject);
  340.             fprintf(options->xmlOutput, "   <pk-algorithm>%s</pk-algorithm>\n", outputData->pkAlgorithm);
  341.             fprintf(options->xmlOutput, "   <pk error=\"%s\" type=\"%s\" bits=\"%d\">\n%s   </pk>\n",
  342.                 outputData->pkError ? "true":"false",
  343.                 outputData->pkType,
  344.                 outputData->pkBits,
  345.                 outputData->pk);
  346.             fprintf(options->xmlOutput, "   <X509v3-Extensions>\n");
  347.             outputCertExtensionsXML(options, outputData->firstCertExt);
  348.             fprintf(options->xmlOutput, "   </X509v3-Extensions>\n");
  349.             fprintf(options->xmlOutput, "   <verify error=\"%s\">%s</verify>\n",
  350.                 outputData->verifyError ? "true":"false",
  351.                 outputData->verifyError ? outputData->verifyErrorString:"");
  352.             fprintf(options->xmlOutput, "  </certificate>\n");
  353.             fflush(options->xmlOutput);
  354.         }
  355.     }
  356.     return true;
  357. }
  358.  
  359. int outputCipher( struct sslCheckOptions *options, struct cipherOutput *outputData )
  360. {
  361.     if ((strcmp(outputData->status, "accepted") == 0) || // Status is accepted
  362.         (options->noFailed == false) // Include failed ciphers
  363.         )
  364.     {
  365.         if (options->quiet == false)
  366.         {
  367.             printf("    %-8s  %s  %3d bits  %s\n",
  368.                 outputData->status,
  369.                 outputData->sslVersion,
  370.                 outputData->cipherBits,
  371.                 outputData->cipherName
  372.                 );
  373.         }
  374.  
  375.         if (options->pout)
  376.         {
  377.             printf("|| %s || %s || %3d || %s ||\n",
  378.                 outputData->status,
  379.                 outputData->sslVersion,
  380.                 outputData->cipherBits,
  381.                 outputData->cipherName
  382.                 );
  383.         }
  384.  
  385.         if (options->xmlOutput != 0)
  386.         {
  387.             fprintf(options->xmlOutput, "  <cipher status=\"%s\" sslversion=\"%s\" bits=\"%d\" cipher=\"%s\" kx=\"%s\" au=\"%s\" enc=\"%s\" mac=\"%s\" />\n",
  388.                 outputData->status,
  389.                 outputData->sslVersion,
  390.                 outputData->cipherBits,
  391.                 outputData->cipherName,
  392.                 outputData->cipherKx,
  393.                 outputData->cipherAu,
  394.                 outputData->cipherEnc,
  395.                 outputData->cipherMac);
  396.             fflush(options->xmlOutput);
  397.         }
  398.     }
  399.     return true;
  400. }
  401.  
  402. int outputPreferedCipher( struct sslCheckOptions *options, struct cipherOutput *outputData )
  403. {
  404.     if (strcmp(outputData->status, "accepted") == 0)
  405.     {
  406.         if (options->quiet == false)
  407.         {
  408.             printf("    %s  %3d bits  %s\n",
  409.                 outputData->sslVersion,
  410.                 outputData->cipherBits,
  411.                 outputData->cipherName
  412.                 );
  413.         }
  414.  
  415.         if (options->pout)
  416.         {
  417.             printf("|| %s || %3d || %s ||\n",
  418.                 outputData->sslVersion,
  419.                 outputData->cipherBits,
  420.                 outputData->cipherName
  421.                 );
  422.         }
  423.  
  424.         if (options->xmlOutput != 0)
  425.         {
  426.             fprintf(options->xmlOutput, "  <defaultcipher sslversion=\"%s\" bits=\"%d\" cipher=\"%s\" kx=\"%s\" au=\"%s\" enc=\"%s\" mac=\"%s\" />\n",
  427.                 outputData->sslVersion,
  428.                 outputData->cipherBits,
  429.                 outputData->cipherName,
  430.                 outputData->cipherKx,
  431.                 outputData->cipherAu,
  432.                 outputData->cipherEnc,
  433.                 outputData->cipherMac);
  434.             fflush(options->xmlOutput);
  435.         }
  436.     }
  437.     return true;
  438. }
  439.  
  440. int freeCertExtOutput( struct certificateExtensionOutput *certExtOut )
  441. {
  442.     struct certificateExtensionOutput *certExtOutPtr;
  443.  
  444.     while (certExtOut != 0)
  445.     {
  446.         certExtOutPtr = certExtOut->next;
  447.         FREEIFNOTNULL(certExtOut->name);
  448.         FREEIFNOTNULL(certExtOut->data);
  449.         FREEIFNOTNULL(certExtOut);
  450.         certExtOut = certExtOutPtr;
  451.     }
  452.  
  453.     return true;
  454. }
  455.  
  456. struct certificateOutput * newCertOutput( void )
  457. {
  458.     struct certificateOutput *myCertOutput;
  459.     myCertOutput = calloc(1,sizeof( struct certificateOutput));
  460.     if (myCertOutput != NULL)
  461.     {
  462.         // Initialize the variables
  463.         myCertOutput->notValidAfter = NULL;
  464.         myCertOutput->notValidBefore = NULL;
  465.         myCertOutput->pk = NULL;
  466.         myCertOutput->firstCertExt = NULL;
  467.     }
  468.     return( myCertOutput );
  469. }
  470.  
  471. struct cipherOutput * newCipherOutput( void )
  472. {
  473.     struct cipherOutput *myCipherOutput;
  474.     myCipherOutput = calloc(1,sizeof(struct cipherOutput));
  475.  
  476.     return( myCipherOutput );
  477. }
  478.  
  479. struct renegotiationOutput * newRenegotiationOutput( void )
  480. {
  481.     struct renegotiationOutput *myRenOut;
  482.     myRenOut = calloc(1,sizeof(struct renegotiationOutput));
  483.     return( myRenOut );
  484. }
  485.  
  486. int freeRenegotiationOutput( struct renegotiationOutput *myRenOut )
  487. {
  488.     FREEIFNOTNULL(myRenOut);
  489.     return true;
  490. }
  491.  
  492. int freeCipherOutput( struct cipherOutput *myCipherOutput )
  493. {
  494.     FREEIFNOTNULL(myCipherOutput);
  495.     return true;
  496. }
  497.  
  498. struct certificateExtensionOutput * newCertExtOutput( void )
  499. {
  500.     struct certificateExtensionOutput *myCertExtOutput;
  501.     myCertExtOutput = calloc(1,sizeof( struct certificateExtensionOutput));
  502.     if (myCertExtOutput != NULL)
  503.     {
  504.         // Initialize the variables
  505.         myCertExtOutput->next = NULL;
  506.     }
  507.     return( myCertExtOutput );
  508. }
  509.  
  510. int freeCertOutput( struct certificateOutput *certOut )
  511. {
  512.     FREEIFNOTNULL(certOut->notValidBefore);
  513.     FREEIFNOTNULL(certOut->notValidAfter);
  514.     FREEIFNOTNULL(certOut->pk);
  515.     // if Certificate Extension
  516.     if( certOut->firstCertExt != NULL )
  517.         freeCertExtOutput( certOut->firstCertExt );
  518.  
  519.     return true;
  520. }
  521.  
  522.  
  523. int parseDescription( char *description, struct cipherOutput *dest )
  524. {
  525.     sscanf(description, "%*s %*s Kx=%s Au=%s Enc=%s Mac=%s",
  526.         dest->cipherKx,
  527.         dest->cipherAu,
  528.         dest->cipherEnc,
  529.         dest->cipherMac);
  530.     return true;
  531. }
  532.  
  533. void setBlocking(SSL * ssl)
  534. {
  535. #if defined (WIN32)
  536.     int fd, res;
  537.     u_long iMode = 0;
  538.     if( (fd = SSL_get_rfd(ssl)) )      
  539.     {
  540.         res = ioctlsocket(fd, FIONBIO, &iMode);
  541.         if( res )
  542.         {
  543.             // Something went wrong...
  544.             dwError = WSAGetLastError();
  545.             if (dwError != 0) {
  546.                     fprintf(stderr, "ERROR in set_blocking(): %ld.\n", dwError);
  547.             }
  548.         }
  549.     }
  550. #else
  551.   int fd, flags;      
  552.  
  553.   /* SSL_get_rfd returns -1 on error */
  554.   if( (fd = SSL_get_rfd(ssl)) )      
  555.   {
  556.     flags = fcntl(fd, F_GETFL);
  557.     flags &= ~O_NONBLOCK;
  558.     fcntl(fd, F_SETFL, flags);
  559.   }
  560.  
  561.   /* SSL_get_wfd returns -1 on error */  
  562.   if( (fd = SSL_get_wfd(ssl)) )      
  563.   {
  564.     flags = fcntl(fd, F_GETFL);
  565.     flags &= ~O_NONBLOCK;
  566.     fcntl(fd, F_SETFL, flags);
  567.   }
  568. #endif
  569. }
  570.  
  571. // Adds Ciphers to the Cipher List structure
  572. int populateCipherList(struct sslCheckOptions *options, SSL_METHOD *sslMethod)
  573. {
  574.     // Variables...
  575.     int returnCode = true;
  576.     struct sslCipher *sslCipherPointer;
  577.     int tempInt;
  578.     int loop;
  579.     STACK_OF(SSL_CIPHER) *cipherList;
  580.     SSL *ssl = NULL;
  581.  
  582.     // Setup Context Object...
  583.     options->ctx = SSL_CTX_new(sslMethod);
  584.     if (options->ctx != NULL)
  585.     {
  586.         SSL_CTX_set_cipher_list(options->ctx, CIPHER_MASK);
  587.  
  588.         // Create new SSL object
  589.         ssl = SSL_new(options->ctx);
  590.         if (ssl != NULL)
  591.         {
  592.             // Get List of Ciphers
  593.             cipherList = SSL_get_ciphers(ssl);
  594.    
  595.             // Create Cipher Struct Entries...
  596.             for (loop = 0; loop < sk_SSL_CIPHER_num(cipherList); loop++)
  597.             {
  598.                 // Create Structure...
  599.                 if (options->ciphers == 0)
  600.                 {
  601.                     options->ciphers = calloc(1,sizeof(struct sslCipher));
  602.                     sslCipherPointer = options->ciphers;
  603.                 }
  604.                 else
  605.                 {
  606.                     sslCipherPointer = options->ciphers;
  607.                     while (sslCipherPointer->next != 0)
  608.                         sslCipherPointer = sslCipherPointer->next;
  609.                     sslCipherPointer->next = calloc(1,sizeof(struct sslCipher));
  610.                     sslCipherPointer = sslCipherPointer->next;
  611.                 }
  612.    
  613.    
  614.                 // Add cipher information...
  615.                 sslCipherPointer->sslMethod = sslMethod;
  616.                 sslCipherPointer->name = SSL_CIPHER_get_name(sk_SSL_CIPHER_value(cipherList, loop));
  617.                 sslCipherPointer->version = SSL_CIPHER_get_version(sk_SSL_CIPHER_value(cipherList, loop));
  618.                 SSL_CIPHER_description(sk_SSL_CIPHER_value(cipherList, loop), sslCipherPointer->description, MAXSTRLEN(sslCipherPointer->description));
  619.                 sslCipherPointer->bits = SSL_CIPHER_get_bits(sk_SSL_CIPHER_value(cipherList, loop), &tempInt);
  620.             }
  621.    
  622.             // Free SSL object
  623.             SSL_free(ssl);
  624.         }
  625.         else
  626.         {
  627.             returnCode = false;
  628.             fprintf(stderr, "ERROR: Could not create SSL object.\n");
  629.         }
  630.  
  631.         // Free CTX Object
  632.         SSL_CTX_free(options->ctx);
  633.     }
  634.  
  635.     // Error Creating Context Object
  636.     else
  637.     {
  638.         returnCode = false;
  639.         fprintf(stderr, "ERROR: Could not create CTX object.\n");
  640.     }
  641.  
  642.     return returnCode;
  643. }
  644.  
  645.  
  646. // File Exists
  647. int fileExists(char *fileName)
  648. {
  649.     // Variables...
  650.     struct stat fileStats;
  651.  
  652.     if (stat(fileName, &fileStats) == 0)
  653.         return true;
  654.     else
  655.         return false;
  656. }
  657.  
  658.  
  659. // Read a line from the input...
  660. void readLine(FILE *input, char *lineFromFile, int maxSize)
  661. {
  662.     // Variables...
  663.     int stripPointer;
  664.  
  665.     // Read line from file...
  666.     fgets(lineFromFile, maxSize, input);
  667.  
  668.     // Clear the end-of-line stuff...
  669.     stripPointer = strlen(lineFromFile) -1;
  670.     while ((lineFromFile[stripPointer] == '\r') || (lineFromFile[stripPointer] == '\n') || (lineFromFile[stripPointer] == ' '))
  671.     {
  672.         lineFromFile[stripPointer] = 0;
  673.         stripPointer--;
  674.     }
  675. }
  676.  
  677.  
  678. // Create a TCP socket
  679. int tcpConnect(struct sslCheckOptions *options)
  680. {
  681.     // Variables...
  682.     int socketDescriptor;
  683.     char buffer[BUFFERSIZE];
  684.     struct sockaddr_in localAddress;
  685.     int status;
  686.  
  687.     // Create Socket
  688.     socketDescriptor = socket(AF_INET, SOCK_STREAM, 0);
  689.     if(socketDescriptor < 0)
  690.     {
  691.         fprintf(stderr, "ERROR: Could not open a socket.\n");
  692.         return 0;
  693.     }
  694.  
  695.     // Configure Local Port
  696.     localAddress.sin_family = AF_INET;
  697.     localAddress.sin_addr.s_addr = htonl(INADDR_ANY);
  698.     localAddress.sin_port = htons(0);
  699.     status = bind(socketDescriptor, (struct sockaddr *) &localAddress, sizeof(localAddress));
  700.     if(status < 0)
  701.     {
  702.         fprintf(stderr, "ERROR: Could not bind to port.\n");
  703.         return 0;
  704.     }
  705.  
  706.     // Connect
  707.     status = connect(socketDescriptor, (struct sockaddr *) &options->serverAddress, sizeof(options->serverAddress));
  708.     if(status < 0)
  709.     {
  710.         fprintf(stderr, "ERROR: Could not open a connection to host %s on port %d.\n", options->host, options->port);
  711.         return 0;
  712.     }
  713.  
  714.     // If STARTTLS is required...
  715.     if (options->starttls == true)
  716.     {
  717.         memset(buffer, 0, BUFFERSIZE);
  718.         recv(socketDescriptor, buffer, BUFFERSIZE - 1, 0);
  719.         if (strncmp(buffer, "220", 3) != 0)
  720.         {
  721.             CLOSESOCKET(socketDescriptor);
  722.             fprintf(stderr, "ERROR: The host %s on port %d did not appear to be an SMTP service.\n", options->host, options->port);
  723.             return 0;
  724.         }
  725.         send(socketDescriptor, "EHLO titania.co.uk\r\n", 20, 0);
  726.         memset(buffer, 0, BUFFERSIZE);
  727.         recv(socketDescriptor, buffer, BUFFERSIZE - 1, 0);
  728.         if (strncmp(buffer, "250", 3) != 0)
  729.         {
  730.             CLOSESOCKET(socketDescriptor);
  731.             fprintf(stderr, "ERROR: The SMTP service on %s port %d did not respond with status 250 to our HELO.\n", options->host, options->port);
  732.             return 0;
  733.         }
  734.         send(socketDescriptor, "STARTTLS\r\n", 10, 0);
  735.         memset(buffer, 0, BUFFERSIZE);
  736.         recv(socketDescriptor, buffer, BUFFERSIZE - 1, 0);
  737.         if (strncmp(buffer, "220", 3) != 0)
  738.         {
  739.             CLOSESOCKET(socketDescriptor);
  740.             fprintf(stderr, "ERROR: The SMTP service on %s port %d did not appear to support STARTTLS.\n", options->host, options->port);
  741.             return 0;
  742.         }
  743.     }
  744.  
  745.     setConnectionTimeout(socketDescriptor, 30000);
  746.  
  747.     // Return
  748.     return socketDescriptor;
  749. }
  750.  
  751.  
  752. // Private Key Password Callback...
  753. static int password_callback(char *buf, int size, int rwflag, void *userdata)
  754. {
  755.     strncpy(buf, (char *)userdata, size);
  756.     buf[strlen(userdata)] = 0;
  757.     return strlen(userdata);
  758. }
  759.  
  760.  
  761. // Load client certificates/private keys...
  762. int loadCerts(struct sslCheckOptions *options)
  763. {
  764.     // Variables...
  765.     int status = 1;
  766.     PKCS12 *pk12 = NULL;
  767.     FILE *pk12File = NULL;
  768.     X509 *cert = NULL;
  769.     EVP_PKEY *pkey = NULL;
  770.     STACK_OF(X509) *ca = NULL;
  771.  
  772.     // Configure PKey password...
  773.     if (options->privateKeyPassword != 0)
  774.     {
  775.         SSL_CTX_set_default_passwd_cb_userdata(options->ctx, (void *)options->privateKeyPassword);
  776.         SSL_CTX_set_default_passwd_cb(options->ctx, password_callback);
  777.     }
  778.  
  779.     // Seperate Certs and PKey Files...
  780.     if ((options->clientCertsFile != 0) && (options->privateKeyFile != 0))
  781.     {
  782.         // Load Cert...
  783.         if (!SSL_CTX_use_certificate_file(options->ctx, options->clientCertsFile, SSL_FILETYPE_PEM))
  784.         {
  785.             if (!SSL_CTX_use_certificate_file(options->ctx, options->clientCertsFile, SSL_FILETYPE_ASN1))
  786.             {
  787.                 if (!SSL_CTX_use_certificate_chain_file(options->ctx, options->clientCertsFile))
  788.                 {
  789.                     fprintf(stderr, "Could not configure certificate(s).\n");
  790.                     status = 0;
  791.                 }
  792.             }
  793.         }
  794.  
  795.         // Load PKey...
  796.         if (status != 0)
  797.         {
  798.             if (!SSL_CTX_use_PrivateKey_file(options->ctx, options->privateKeyFile, SSL_FILETYPE_PEM))
  799.             {
  800.                 if (!SSL_CTX_use_PrivateKey_file(options->ctx, options->privateKeyFile, SSL_FILETYPE_ASN1))
  801.                 {
  802.                     if (!SSL_CTX_use_RSAPrivateKey_file(options->ctx, options->privateKeyFile, SSL_FILETYPE_PEM))
  803.                     {
  804.                         if (!SSL_CTX_use_RSAPrivateKey_file(options->ctx, options->privateKeyFile, SSL_FILETYPE_ASN1))
  805.                         {
  806.                             fprintf(stderr, "Could not configure private key.\n");
  807.                             status = 0;
  808.                         }
  809.                     }
  810.                 }
  811.             }
  812.         }
  813.     }
  814.  
  815.     // PKCS Cert and PKey File...
  816.     else if (options->privateKeyFile != 0)
  817.     {
  818.         pk12File = fopen(options->privateKeyFile, "rb");
  819.         if (pk12File != NULL)
  820.         {
  821.             pk12 = d2i_PKCS12_fp(pk12File, NULL);
  822.             if (!pk12)
  823.             {
  824.                 status = 0;
  825.                 fprintf(stderr, "Could not read PKCS#12 file.\n");
  826.             }
  827.             else
  828.             {
  829.                 if (!PKCS12_parse(pk12, options->privateKeyPassword, &pkey, &cert, &ca))
  830.                 {
  831.                     status = 0;
  832.                     fprintf(stderr, "Error parsing PKCS#12. Are you sure that password was correct?\n");
  833.                 }
  834.                 else
  835.                 {
  836.                     if (!SSL_CTX_use_certificate(options->ctx, cert))
  837.                     {
  838.                         status = 0;
  839.                         fprintf(stderr, "Could not configure certificate.\n");
  840.                     }
  841.                     if (!SSL_CTX_use_PrivateKey(options->ctx, pkey))
  842.                     {
  843.                         status = 0;
  844.                         fprintf(stderr, "Could not configure private key.\n");
  845.                     }
  846.                 }
  847.                 PKCS12_free(pk12);
  848.             }
  849.             fclose(pk12File);
  850.         }
  851.         else
  852.         {
  853.             fprintf(stderr, "Could not open PKCS#12 file.\n");
  854.             status = 0;
  855.         }
  856.     }
  857.  
  858.     // Check Cert/Key...
  859.     if (status != 0)
  860.     {
  861.         if (!SSL_CTX_check_private_key(options->ctx))
  862.         {
  863.             fprintf(stderr, "Private key does not match certificate.\n");
  864.             return false;
  865.         }
  866.         else
  867.             return true;
  868.     }
  869.     else
  870.         return false;
  871. }
  872.  
  873.  
  874. // Test a cipher...
  875. int testCipher(struct sslCheckOptions *options, struct sslCipher *sslCipherPointer)
  876. {
  877.     // Variables...
  878.     int cipherStatus;
  879.     int status = true;
  880.     int socketDescriptor = 0;
  881.     SSL *ssl = NULL;
  882.     BIO *cipherConnectionBio;
  883.     BIO *stdoutBIO = NULL;
  884.     char requestBuffer[BUFFERSIZE];
  885.     char buffer[50];
  886.     int resultSize = 0;
  887.     struct cipherOutput *myCipherOutput = newCipherOutput();
  888.  
  889.     // Create request buffer...
  890.     memset(requestBuffer, 0, BUFFERSIZE);
  891.     snprintf(requestBuffer, MAXSTRLEN(requestBuffer), "GET / HTTP/1.0\r\nUser-Agent: SSLScan/%s\r\nHost: %s\r\n\r\n", SSLSCAN_VERSION, options->host);
  892.     //snprintf(requestBuffer, MAXSTRLEN(requestBuffer), "GET / HTTP/1.0\r\nUser-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6\r\nHost: %s\r\n\r\n", options->host);
  893.     // Connect to host
  894.     socketDescriptor = tcpConnect(options);
  895.     if (socketDescriptor != 0)
  896.     {
  897.  
  898.         if (SSL_CTX_set_cipher_list(options->ctx, sslCipherPointer->name) != 0)
  899.         {
  900.  
  901.             // Create SSL object...
  902.             ssl = SSL_new(options->ctx);
  903.             if (ssl != NULL)
  904.             {
  905.                 // Connect socket and BIO
  906.                 cipherConnectionBio = BIO_new_socket(socketDescriptor, BIO_NOCLOSE);
  907.  
  908.                 // Connect SSL and BIO
  909.                 SSL_set_bio(ssl, cipherConnectionBio, cipherConnectionBio);
  910.  
  911.                 // Connect SSL over socket
  912.                 cipherStatus = SSL_connect(ssl);
  913.  
  914.                 // Show Cipher Status
  915.                 if (!((options->noFailed == true) && (cipherStatus != 1)))
  916.                 {
  917.                     if (cipherStatus == 1)
  918.                     {
  919.                         snprintf(myCipherOutput->status, MAXSTRLEN(myCipherOutput->status), "accepted");
  920.                         if (options->http == true)
  921.                         {
  922.                             // Stdout BIO...
  923.                             stdoutBIO = BIO_new(BIO_s_file());
  924.                             BIO_set_fp(stdoutBIO, stdout, BIO_NOCLOSE);
  925.  
  926.                             // HTTP Get...
  927.                             SSL_write(ssl, requestBuffer, sizeof(requestBuffer));
  928.                             memset(buffer ,0 , 50);
  929.                             resultSize = SSL_read(ssl, buffer, 49);
  930.                             if (resultSize > 9)
  931.                             {
  932.                                 int loop = 0;
  933.                                 for (loop = 9; (loop < 49) && (buffer[loop] != 0) && (buffer[loop] != '\r') && (buffer[loop] != '\n'); loop++)
  934.                                 { }
  935.                                 buffer[loop] = 0;
  936.  
  937.                                 // Output HTTP code...
  938.                                 snprintf(myCipherOutput->L4String, MAXSTRLEN(myCipherOutput->L4String), "%s", buffer + 9);
  939.                             }
  940.                             else
  941.                             {
  942.                                 snprintf(myCipherOutput->L4String, MAXSTRLEN(myCipherOutput->L4String), "");
  943.                             }
  944.                         }
  945.                     }
  946.                     else if (cipherStatus == 0)
  947.                     {
  948.                         snprintf(myCipherOutput->status, MAXSTRLEN(myCipherOutput->status), "rejected");
  949.                         if (options->http == true)
  950.                         {
  951.                             snprintf(myCipherOutput->L4String, MAXSTRLEN(myCipherOutput->L4String), "N/A");
  952.                         }
  953.                     }
  954.                     else
  955.                     {
  956.                         snprintf(myCipherOutput->status, MAXSTRLEN(myCipherOutput->status), "failed");
  957.                         if (options->http == true)
  958.                         {
  959.                             snprintf(myCipherOutput->L4String, MAXSTRLEN(myCipherOutput->L4String), "N/A");
  960.                         }
  961.                     }
  962.  
  963.                     if (sslCipherPointer->sslMethod == SSLv2_client_method())
  964.                     {
  965.                         snprintf(myCipherOutput->sslVersion, MAXSTRLEN(myCipherOutput->sslVersion), "SSLv2  ");
  966.                     }
  967.                     else if (sslCipherPointer->sslMethod == SSLv3_client_method())
  968.                     {
  969.                         snprintf(myCipherOutput->sslVersion, MAXSTRLEN(myCipherOutput->sslVersion), "SSLv3  ");
  970.                     }
  971.                     else if (sslCipherPointer->sslMethod == TLSv1_client_method())
  972.                     {
  973.                         snprintf(myCipherOutput->sslVersion, MAXSTRLEN(myCipherOutput->sslVersion), "TLSv1  ");
  974.                     }
  975.                     else if (sslCipherPointer->sslMethod == TLSv1_1_client_method())
  976.                     {
  977.                         snprintf(myCipherOutput->sslVersion, MAXSTRLEN(myCipherOutput->sslVersion), "TLSv1.1");
  978.                     }
  979.                     else if (sslCipherPointer->sslMethod == TLSv1_2_client_method())
  980.                     {
  981.                         snprintf(myCipherOutput->sslVersion, MAXSTRLEN(myCipherOutput->sslVersion), "TLSv1.2");
  982.                     }
  983.                     else
  984.                     {
  985.                         snprintf(myCipherOutput->sslVersion, MAXSTRLEN(myCipherOutput->sslVersion), "Unknown");
  986.                     }
  987.  
  988.                     myCipherOutput->cipherBits = sslCipherPointer->bits;
  989.                     parseDescription(sslCipherPointer->description, myCipherOutput);
  990.                     snprintf(myCipherOutput->cipherName, MAXSTRLEN(myCipherOutput->cipherName), "%s", sslCipherPointer->name);
  991.                 }
  992.  
  993.                 // Disconnect SSL over socket
  994.                 if (cipherStatus == 1)
  995.                     SSL_shutdown(ssl);
  996.  
  997.                 // Free SSL object
  998.                 SSL_free(ssl);
  999.             }
  1000.             else
  1001.             {
  1002.                 status = false;
  1003.                 fprintf(stderr, "ERROR: Could create SSL object.\n");
  1004.             }
  1005.         }
  1006.         else
  1007.         {
  1008.             status = false;
  1009.             fprintf(stderr, "ERROR: Could set cipher %s.\n", sslCipherPointer->name);
  1010.         }
  1011.  
  1012.         // Disconnect from host
  1013.         CLOSESOCKET(socketDescriptor);
  1014.     }
  1015.  
  1016.     // Could not connect
  1017.     else
  1018.         status = false;
  1019.  
  1020.     outputCipher( options, myCipherOutput );
  1021.     FREEIFNOTNULL(myCipherOutput);
  1022.  
  1023.     return status;
  1024. }
  1025.  
  1026. // Check if the server supports renegotiation
  1027. int testRenegotiation(struct sslCheckOptions *options, SSL_METHOD *sslMethod)
  1028. {
  1029.     // Variables...
  1030.     int cipherStatus;
  1031.     int status = true;
  1032.     int secure = false;
  1033.     int socketDescriptor = 0;
  1034.     int res;
  1035.     SSL *ssl = NULL;
  1036.     BIO *cipherConnectionBio;
  1037.     struct renegotiationOutput *renOut = newRenegotiationOutput();
  1038.  
  1039.     // Connect to host
  1040.     socketDescriptor = tcpConnect(options);
  1041.     if (socketDescriptor != 0)
  1042.     {
  1043.  
  1044.         // Setup Context Object...
  1045.         options->ctx = SSL_CTX_new(sslMethod);
  1046.         if (options->ctx != NULL)
  1047.         {
  1048.             if (SSL_CTX_set_cipher_list(options->ctx, CIPHER_MASK) != 0)
  1049.             {
  1050.  
  1051.                 // Load Certs if required...
  1052.                 if ((options->clientCertsFile != 0) || (options->privateKeyFile != 0))
  1053.                     status = loadCerts(options);
  1054.  
  1055.                 if (status == true)
  1056.                 {
  1057.                     // Create SSL object...
  1058.                     ssl = SSL_new(options->ctx);
  1059. #if ( OPENSSL_VERSION_NUMBER > 0x009080cfL )
  1060.                     // Make sure we can connect to insecure servers
  1061.                     // OpenSSL is going to change the default at a later date
  1062.                     SSL_set_options(ssl, SSL_OP_LEGACY_SERVER_CONNECT);
  1063. #endif
  1064.                     if (ssl != NULL)
  1065.                     {
  1066.                         // Connect socket and BIO
  1067.                         cipherConnectionBio = BIO_new_socket(socketDescriptor, BIO_NOCLOSE);
  1068.  
  1069.                         // Connect SSL and BIO
  1070.                         SSL_set_bio(ssl, cipherConnectionBio, cipherConnectionBio);
  1071.  
  1072.                         // Connect SSL over socket
  1073.                         cipherStatus = SSL_connect(ssl);
  1074.  
  1075.                         if (cipherStatus == 1)
  1076.                         {
  1077. #if defined(_GET_SECURE_RENEGOTIATION)
  1078.                             // SSL_get_secure_renegotiation_support() appeared first in OpenSSL 0.9.8m
  1079.                             renOut->secure = SSL_get_secure_renegotiation_support(ssl);
  1080.                             if( renOut->secure )
  1081.                             {
  1082.                                 // If it supports secure renegotiations,
  1083.                                 // it should have renegotioation support in general
  1084.                                 renOut->supported = true;
  1085.                                 status = true;
  1086.                             }
  1087.                             else
  1088.                             {
  1089. #endif
  1090.                                 // We can't assume that just because the secure renegotiation
  1091.                                 // support failed the server doesn't support insecure renegotiations
  1092.  
  1093.                                 // assume ssl is connected and error free up to here
  1094.                                 //setBlocking(ssl); // this is unnecessary if it is already blocking
  1095.                                 SSL_renegotiate(ssl); // Ask to renegotiate the connection
  1096.                                 SSL_do_handshake(ssl); // Send renegotiation request to server
  1097.  
  1098.                                 if (ssl->state == SSL_ST_OK)
  1099.                                 {
  1100.                                     res = SSL_do_handshake(ssl); // Send renegotiation request to server
  1101.                                     if( res != 1 )
  1102.                                     {
  1103.                                         fprintf(stderr, "\n\nSSL_do_handshake() call failed\n");
  1104.                                     }
  1105.                                     if (ssl->state == SSL_ST_OK)
  1106.                                     {
  1107.                                         /* our renegotiation is complete */
  1108.                                         renOut->supported = true;
  1109.                                         status = true;
  1110.                                     } else {
  1111.                                         renOut->supported = false;
  1112.                                         status = false;
  1113.                                         fprintf(stderr, "\n\nFailed to complete renegotiation\n");
  1114.                                     }
  1115.                                 } else {
  1116.                                     status = false;
  1117.                                     renOut->secure = false;
  1118.                                 }
  1119. #if defined(_GET_SECURE_RENEGOTIATION)
  1120.                             }
  1121. #endif
  1122.                             // Disconnect SSL over socket
  1123.                             SSL_shutdown(ssl);
  1124.                         }
  1125.  
  1126.                         // Free SSL object
  1127.                         SSL_free(ssl);
  1128.                     }
  1129.                     else
  1130.                     {
  1131.                         status = false;
  1132.                         renOut->supported = false;
  1133.                         fprintf(stderr, "ERROR: Could create SSL object.\n");
  1134.                     }
  1135.                 }
  1136.             }
  1137.             else
  1138.             {
  1139.                 status = false;
  1140.                 renOut->supported = false;
  1141.                 fprintf(stderr, "ERROR: Could set cipher.\n");
  1142.             }
  1143.            
  1144.             // Free CTX Object
  1145.             SSL_CTX_free(options->ctx);
  1146.         }
  1147.    
  1148.         // Error Creating Context Object
  1149.         else
  1150.         {
  1151.             status = false;
  1152.             renOut->supported = false;
  1153.             fprintf(stderr, "ERROR: Could not create CTX object.\n");
  1154.         }
  1155.  
  1156.         // Disconnect from host
  1157.         CLOSESOCKET(socketDescriptor);
  1158.     }
  1159.     else
  1160.     {
  1161.         // Could not connect
  1162.         renOut->supported = false;
  1163.         status = false;
  1164.     }
  1165.     outputRenegotiaition(options, renOut);
  1166.     freeRenegotiationOutput( renOut );
  1167.  
  1168.     return status;          
  1169.  
  1170. }
  1171.  
  1172.  
  1173. // Test for prefered ciphers
  1174. int defaultCipher(struct sslCheckOptions *options, SSL_METHOD *sslMethod)
  1175. {
  1176.     // Variables...
  1177.     int cipherStatus;
  1178.     int status = true;
  1179.     int socketDescriptor = 0;
  1180.     SSL *ssl = NULL;
  1181.     BIO *cipherConnectionBio;
  1182.     int tempInt2;
  1183.     struct cipherOutput *myCipherOutput = newCipherOutput();
  1184.  
  1185.     // Connect to host
  1186.     socketDescriptor = tcpConnect(options);
  1187.     if (socketDescriptor != 0)
  1188.     {
  1189.  
  1190.         // Setup Context Object...
  1191.         options->ctx = SSL_CTX_new(sslMethod);
  1192.         if (options->ctx != NULL)
  1193.         {
  1194.             if (SSL_CTX_set_cipher_list(options->ctx, CIPHER_MASK) != 0)
  1195.             {
  1196.  
  1197.                 // Load Certs if required...
  1198.                 if ((options->clientCertsFile != 0) || (options->privateKeyFile != 0))
  1199.                     status = loadCerts(options);
  1200.  
  1201.                 if (status == true)
  1202.                 {
  1203.                     // Create SSL object...
  1204.                     ssl = SSL_new(options->ctx);
  1205.                     if (ssl != NULL)
  1206.                     {
  1207.                         // Connect socket and BIO
  1208.                         cipherConnectionBio = BIO_new_socket(socketDescriptor, BIO_NOCLOSE);
  1209.  
  1210.                         // Connect SSL and BIO
  1211.                         SSL_set_bio(ssl, cipherConnectionBio, cipherConnectionBio);
  1212.  
  1213.                         // Connect SSL over socket
  1214.                         cipherStatus = SSL_connect(ssl);
  1215.                         if (cipherStatus == 1)
  1216.                         {
  1217.                             snprintf(myCipherOutput->status, MAXSTRLEN(myCipherOutput->status), "accepted");
  1218.                             if (sslMethod == SSLv2_client_method())
  1219.                             {
  1220.                                 snprintf(myCipherOutput->sslVersion, MAXSTRLEN(myCipherOutput->sslVersion), "SSLv2  ");
  1221.                             }
  1222.                             else if (sslMethod == SSLv3_client_method())
  1223.                             {
  1224.                                 snprintf(myCipherOutput->sslVersion, MAXSTRLEN(myCipherOutput->sslVersion), "SSLv3  ");
  1225.                             }
  1226.                             else if (sslMethod == TLSv1_client_method())
  1227.                             {
  1228.                                 snprintf(myCipherOutput->sslVersion, MAXSTRLEN(myCipherOutput->sslVersion), "TLSv1  ");
  1229.                             }
  1230.                             else if (sslMethod == TLSv1_1_client_method())
  1231.                             {
  1232.                                 snprintf(myCipherOutput->sslVersion, MAXSTRLEN(myCipherOutput->sslVersion), "TLSv1.1");
  1233.                             }
  1234.                             else if (sslMethod == TLSv1_2_client_method())
  1235.                             {
  1236.                                 snprintf(myCipherOutput->sslVersion, MAXSTRLEN(myCipherOutput->sslVersion), "TLSv1.2");
  1237.                             }
  1238.                             else
  1239.                             {
  1240.                                 snprintf(myCipherOutput->sslVersion, MAXSTRLEN(myCipherOutput->sslVersion), "Unknown");
  1241.                             }
  1242.  
  1243.                             myCipherOutput->cipherBits = SSL_get_cipher_bits(ssl, &tempInt2);
  1244.                             parseDescription(options->ciphers->description, myCipherOutput);
  1245.                             snprintf(myCipherOutput->cipherName, MAXSTRLEN(myCipherOutput->cipherName), "%s", SSL_get_cipher_name(ssl));
  1246.  
  1247.                             // Disconnect SSL over socket
  1248.                             SSL_shutdown(ssl);
  1249.                         }
  1250.                         else
  1251.                         {
  1252.                             snprintf(myCipherOutput->status, MAXSTRLEN(myCipherOutput->status), "error");
  1253.                         }
  1254.  
  1255.                         // Free SSL object
  1256.                         SSL_free(ssl);
  1257.                     }
  1258.                     else
  1259.                     {
  1260.                         status = false;
  1261.                         snprintf(myCipherOutput->status, MAXSTRLEN(myCipherOutput->status), "error");
  1262.                         fprintf(stderr, "ERROR: Could create SSL object.\n");
  1263.                     }
  1264.                 }
  1265.             }
  1266.             else
  1267.             {
  1268.                 status = false;
  1269.                 fprintf(stderr, "ERROR: Could set cipher.\n");
  1270.             }
  1271.            
  1272.             // Free CTX Object
  1273.             SSL_CTX_free(options->ctx);
  1274.         }
  1275.    
  1276.         // Error Creating Context Object
  1277.         else
  1278.         {
  1279.             status = false;
  1280.             fprintf(stderr, "ERROR: Could not create CTX object.\n");
  1281.         }
  1282.  
  1283.         // Disconnect from host
  1284.         CLOSESOCKET(socketDescriptor);
  1285.     }
  1286.  
  1287.     // Could not connect
  1288.     else
  1289.         status = false;
  1290.  
  1291.     outputPreferedCipher( options, myCipherOutput );
  1292.     FREEIFNOTNULL( myCipherOutput );
  1293.  
  1294.     return status;
  1295. }
  1296.  
  1297.  
  1298. // Get certificate...
  1299. int getCertificate(struct sslCheckOptions *options)
  1300. {
  1301.     // Variables...
  1302.     int cipherStatus = 0;
  1303.     int status = true;
  1304.     int socketDescriptor = 0;
  1305.     SSL *ssl = NULL;
  1306.     BIO *cipherConnectionBio = NULL;
  1307.     BIO *bio = NULL;
  1308.     BUF_MEM *buf;
  1309.     X509 *x509Cert = NULL;
  1310.     EVP_PKEY *publicKey = NULL;
  1311.     SSL_METHOD *sslMethod = NULL;
  1312.     ASN1_OBJECT *asn1Object = NULL;
  1313.     X509_EXTENSION *extension = NULL;
  1314.     int tempInt = 0;
  1315.     long verifyError = 0;
  1316.     struct certificateOutput *myCertOutput = newCertOutput();
  1317.     struct certificateExtensionOutput *myCertExtOutputPtr;
  1318.  
  1319.     // Connect to host
  1320.     socketDescriptor = tcpConnect(options);
  1321.     if (socketDescriptor != 0)
  1322.     {
  1323.  
  1324.         // Setup Context Object...
  1325.         sslMethod = SSLv23_method();
  1326.         options->ctx = SSL_CTX_new(sslMethod);
  1327.         if (options->ctx != NULL)
  1328.         {
  1329.  
  1330.             if (SSL_CTX_set_cipher_list(options->ctx, CIPHER_MASK) != 0)
  1331.             {
  1332.  
  1333.                 // Load Certs if required...
  1334.                 if ((options->clientCertsFile != 0) || (options->privateKeyFile != 0))
  1335.                     status = loadCerts(options);
  1336.  
  1337.                 if (status == true)
  1338.                 {
  1339.                     // Create SSL object...
  1340.                     ssl = SSL_new(options->ctx);
  1341.                     if (ssl != NULL)
  1342.                     {
  1343.  
  1344.                         // Connect socket and BIO
  1345.                         cipherConnectionBio = BIO_new_socket(socketDescriptor, BIO_NOCLOSE);
  1346.  
  1347.                         // Connect SSL and BIO
  1348.                         SSL_set_bio(ssl, cipherConnectionBio, cipherConnectionBio);
  1349.  
  1350.                         // Connect SSL over socket
  1351.                         cipherStatus = SSL_connect(ssl);
  1352.                         if (cipherStatus == 1)
  1353.                         {
  1354.  
  1355.                             // Setup BIO
  1356.                             BIO_get_mem_ptr(bio, &buf);
  1357.                             bio = BIO_new(BIO_s_mem());
  1358.  
  1359.                             // Get Certificate...
  1360.                             x509Cert = SSL_get_peer_certificate(ssl);
  1361.                             if (x509Cert != NULL)
  1362.                             {
  1363.                                 // Certificate Version
  1364.                                 if (!(X509_FLAG_COMPAT & X509_FLAG_NO_VERSION))
  1365.                                 {
  1366.                                     myCertOutput->version = X509_get_version(x509Cert);
  1367.                                 }
  1368.  
  1369.                                 // Certificate Serial Number
  1370.                                 if (!(X509_FLAG_COMPAT & X509_FLAG_NO_SERIAL))
  1371.                                 {
  1372.                                     myCertOutput->serial = ASN1_INTEGER_get(X509_get_serialNumber(x509Cert));
  1373.                                 }
  1374.  
  1375.                                 // Signature Algorithm
  1376.                                 if (!(X509_FLAG_COMPAT & X509_FLAG_NO_SIGNAME))
  1377.                                 {
  1378.                                     i2t_ASN1_OBJECT(myCertOutput->signatureAlgorithm, MAXSTRLEN(myCertOutput->signatureAlgorithm), x509Cert->cert_info->signature->algorithm);
  1379.                                 }
  1380.  
  1381.                                 // Certificate Issuer
  1382.                                 if (!(X509_FLAG_COMPAT & X509_FLAG_NO_ISSUER))
  1383.                                 {
  1384.                                     X509_NAME_oneline(X509_get_issuer_name(x509Cert), myCertOutput->issuer, MAXSTRLEN(myCertOutput->issuer));
  1385.                                 }
  1386.  
  1387.                                 // Certificate Validity
  1388.                                 if (!(X509_FLAG_COMPAT & X509_FLAG_NO_VALIDITY))
  1389.                                 {
  1390.                                     // notBefore
  1391.                                     BIO_reset(bio);
  1392.                                     ASN1_TIME_print(bio, X509_get_notBefore(x509Cert));
  1393.                                     BIO_get_mem_ptr(bio, &buf);
  1394.                                     myCertOutput->notValidBefore = strndup(buf->data, buf->length);
  1395.                                    
  1396.                                     // notAfter
  1397.                                     BIO_reset(bio);
  1398.                                     ASN1_TIME_print(bio, X509_get_notAfter(x509Cert));
  1399.                                     BIO_get_mem_ptr(bio, &buf);
  1400.                                     myCertOutput->notValidAfter = strndup(buf->data, buf->length);
  1401.                                 }
  1402.  
  1403.                                 // Certificate Subject...
  1404.                                 if (!(X509_FLAG_COMPAT & X509_FLAG_NO_SUBJECT))
  1405.                                 {
  1406.                                     X509_NAME_oneline(X509_get_subject_name(x509Cert), myCertOutput->subject, MAXSTRLEN(myCertOutput->subject));
  1407.                                 }
  1408.  
  1409.                                 // Public Key Algorithm
  1410.                                 if (!(X509_FLAG_COMPAT & X509_FLAG_NO_PUBKEY))
  1411.                                 {
  1412.                                     i2t_ASN1_OBJECT(myCertOutput->pkAlgorithm, MAXSTRLEN(myCertOutput->pkAlgorithm), x509Cert->cert_info->key->algor->algorithm);
  1413.  
  1414.                                     // Public Key...
  1415.                                     publicKey = X509_get_pubkey(x509Cert);
  1416.                                     if (publicKey == NULL)
  1417.                                     {
  1418.                                         // Could not load Public Key
  1419.                                         myCertOutput->pkError = true;
  1420.                                     }
  1421.                                     else
  1422.                                     {
  1423.                                         // Public key loaded just fine
  1424.                                         myCertOutput->pkError = false;
  1425.  
  1426.                                         switch (publicKey->type)
  1427.                                         {
  1428.                                             case EVP_PKEY_RSA:
  1429.                                                 // RSA Public Key
  1430.                                                 snprintf(myCertOutput->pkType, MAXSTRLEN(myCertOutput->pkType), "RSA");
  1431.                                                 BIO_reset(bio);
  1432.                                                 RSA_print(bio, publicKey->pkey.rsa, 6);
  1433.                                                 BIO_get_mem_ptr(bio, &buf);
  1434.                                                 myCertOutput->pk = strndup(buf->data, buf->length);
  1435.  
  1436.                                                 myCertOutput->pkBits = BN_num_bits(publicKey->pkey.rsa->n);
  1437.                                                 break;
  1438.                                             case EVP_PKEY_DSA:
  1439.                                                 // DSA Public Key
  1440.                                                 snprintf(myCertOutput->pkType, MAXSTRLEN(myCertOutput->pkType), "DSA");
  1441.                                                 BIO_reset(bio);
  1442.                                                 DSA_print(bio, publicKey->pkey.dsa, 6);
  1443.                                                 BIO_get_mem_ptr(bio, &buf);
  1444.                                                 myCertOutput->pk = strndup(buf->data, buf->length);
  1445.                                                 myCertOutput->pkBits = -1; // DSA has no bit information
  1446.                                                 break;
  1447.                                             case EVP_PKEY_EC:
  1448.                                                 // EC Public Key
  1449.                                                 snprintf(myCertOutput->pkType, MAXSTRLEN(myCertOutput->pkType), "EC");
  1450.                                                 BIO_reset(bio);
  1451.                                                 EC_KEY_print(bio, publicKey->pkey.ec, 6);
  1452.                                                 BIO_get_mem_ptr(bio, &buf);
  1453.                                                 myCertOutput->pk = strndup(buf->data, buf->length);
  1454.                                                 myCertOutput->pkBits = -1; // EC has no bit information
  1455.                                                 break;
  1456.                                             default:
  1457.                                                 // Unknown Public Key
  1458.                                                 myCertOutput->pkError = true;
  1459.                                                 snprintf(myCertOutput->pkType, MAXSTRLEN(myCertOutput->pkType), "unknown");
  1460.                                                 break;
  1461.                                         }
  1462.  
  1463.                                         EVP_PKEY_free(publicKey);
  1464.                                     }
  1465.                                 }
  1466.  
  1467.                                 // X509 v3...
  1468.                                 if (!(X509_FLAG_COMPAT & X509_FLAG_NO_EXTENSIONS))
  1469.                                 {
  1470.                                     if (sk_X509_EXTENSION_num(x509Cert->cert_info->extensions) > 0)
  1471.                                     {
  1472.                                         // We got extensions!
  1473.                                         myCertOutput->firstCertExt = newCertExtOutput();
  1474.                                         myCertExtOutputPtr = myCertOutput->firstCertExt;
  1475.  
  1476.                                         for (tempInt = 0; tempInt < sk_X509_EXTENSION_num(x509Cert->cert_info->extensions); tempInt++)
  1477.                                         {
  1478.                                             // Find the last certificate output structure
  1479.                                             while (myCertExtOutputPtr->next != 0)
  1480.                                             {
  1481.                                                 myCertExtOutputPtr = myCertExtOutputPtr->next;
  1482.                                             }
  1483.                                             // Initialize the Certificate Extension Ouput structure
  1484.                                             myCertExtOutputPtr->next = newCertExtOutput();
  1485.                                             myCertExtOutputPtr = myCertExtOutputPtr->next;
  1486.  
  1487.                                             // Get Extension...
  1488.                                             extension = sk_X509_EXTENSION_value(x509Cert->cert_info->extensions, tempInt);
  1489.  
  1490.                                             // Get extension name
  1491.                                             asn1Object = X509_EXTENSION_get_object(extension);
  1492.                                             BIO_reset(bio);
  1493.                                             i2a_ASN1_OBJECT(bio, asn1Object);
  1494.                                             BIO_get_mem_ptr(bio, &buf);
  1495.                                             myCertExtOutputPtr->name = strndup(buf->data, buf->length);
  1496.  
  1497.                                             // Get critical bit
  1498.                                             myCertExtOutputPtr->critical = X509_EXTENSION_get_critical(extension);
  1499.                                            
  1500.                                             // Get extension value
  1501.                                             BIO_reset(bio);
  1502.                                             X509V3_EXT_print(bio, extension, X509_FLAG_COMPAT, 0);
  1503.                                             BIO_get_mem_ptr(bio, &buf);
  1504.                                             myCertExtOutputPtr->data = strndup(buf->data, buf->length);
  1505.                                         }
  1506.                                     }
  1507.                                 }
  1508.  
  1509.                                 // Load trusted CAs
  1510.                                 if((options->CAfile != NULL) && (options->CApath != NULL))
  1511.                                 {
  1512.                                     if(!SSL_CTX_load_verify_locations(options->ctx, options->CAfile, options->CApath))
  1513.                                     {
  1514.                                         fprintf(stderr, "ERROR: Failed to load trusted CA file (%s)/CA path (%s)\n", options->CAfile, options->CApath);
  1515.                                     }
  1516.                                 }
  1517.  
  1518.                                 // Verify Certificate...
  1519.                                 verifyError = SSL_get_verify_result(ssl);
  1520.                                 if (verifyError == X509_V_OK)
  1521.                                 {
  1522.                                     // Certificate passed verification
  1523.                                     myCertOutput->verifyError = false;
  1524.                                     snprintf(myCertOutput->verifyErrorString, MAXSTRLEN(myCertOutput->verifyErrorString), "");
  1525.                                 }
  1526.                                 else
  1527.                                 {
  1528.                                     // Certificate failed verification
  1529.                                     myCertOutput->verifyError = true;
  1530.                                     snprintf(myCertOutput->verifyErrorString, MAXSTRLEN(myCertOutput->verifyErrorString), "%s", X509_verify_cert_error_string(verifyError));
  1531.                                 }
  1532.  
  1533.                                 // Free X509 Certificate...
  1534.                                 X509_free(x509Cert);
  1535.                             }
  1536.  
  1537.                             // Free BIO
  1538.                             BIO_free(bio);
  1539.  
  1540.                             // Disconnect SSL over socket
  1541.                             SSL_shutdown(ssl);
  1542.                         }
  1543.  
  1544.                         // Free SSL object
  1545.                         SSL_free(ssl);
  1546.                     }
  1547.                     else
  1548.                     {
  1549.                         status = false;
  1550.                         fprintf(stderr, "ERROR: Could create SSL object.\n");
  1551.                     }
  1552.                 }
  1553.             }
  1554.             else
  1555.             {
  1556.                 status = false;
  1557.                 fprintf(stderr, "ERROR: Could set cipher.\n");
  1558.             }
  1559.  
  1560.             // Free CTX Object
  1561.             SSL_CTX_free(options->ctx);
  1562.         }
  1563.  
  1564.         // Error Creating Context Object
  1565.         else
  1566.         {
  1567.             status = false;
  1568.             fprintf(stderr, "ERROR: Could not create CTX object.\n");
  1569.         }
  1570.  
  1571.         // Disconnect from host
  1572.         CLOSESOCKET(socketDescriptor);
  1573.     }
  1574.  
  1575.     // Could not connect
  1576.     else
  1577.         status = false;
  1578.  
  1579.     outputCertificate( options, myCertOutput );
  1580.     freeCertOutput( myCertOutput );
  1581.  
  1582.     return status;
  1583. }
  1584.  
  1585.  
  1586. // Test a single host and port for ciphers...
  1587. int testHost(struct sslCheckOptions *options)
  1588. {
  1589.     // Variables...
  1590.     struct sslCipher *sslCipherPointer;
  1591.     int status = true;
  1592.     time_t rawtime;
  1593.     struct tm * timeinfo;
  1594.     char datetime[BUFFERSIZE];
  1595.  
  1596.     // Resolve Host Name
  1597. #if defined (WIN32)
  1598.     WORD wVersionRequested;
  1599.     WSADATA wsaData;
  1600.     int err;
  1601.     wVersionRequested = MAKEWORD( 1, 1 );
  1602.     err = WSAStartup( wVersionRequested, &wsaData );
  1603. #endif
  1604.  
  1605.     options->hostStruct = gethostbyname(options->host);
  1606.  
  1607. #if defined (WIN32)
  1608.     dwError = WSAGetLastError();
  1609.     if (dwError != 0) {
  1610.         if (dwError == WSAHOST_NOT_FOUND) {
  1611.             //printf("Host not found\n");
  1612.             fprintf(stderr, "ERROR: Could not resolve hostname %s: Host not found.\n", options->host);
  1613.             return false;
  1614.         } else if (dwError == WSANO_DATA) {
  1615.             //printf("No data record found\n");
  1616.             fprintf(stderr, "ERROR: Could not resolve hostname %s: No data record found.\n", options->host);
  1617.             return false;
  1618.         } else {
  1619.             //printf("Function failed with error: %ld\n", dwError);
  1620.             fprintf(stderr, "ERROR: Could not resolve hostname %s: Error(%ld).\n", options->host, dwError);
  1621.             return false;
  1622.         }
  1623.     }
  1624. #else
  1625.     if (options->hostStruct == NULL)
  1626.     {  
  1627.         fprintf(stderr, "%sERROR: Could not resolve hostname %s.%s\n", COL_RED, options->host, RESET);
  1628.         return false;
  1629.     }
  1630. #endif
  1631.  
  1632.     // Configure Server Address and Port
  1633.     options->serverAddress.sin_family = options->hostStruct->h_addrtype;
  1634.     memcpy((char *) &options->serverAddress.sin_addr.s_addr, options->hostStruct->h_addr_list[0], options->hostStruct->h_length);
  1635.     options->serverAddress.sin_port = htons(options->port);
  1636.  
  1637.     // XML Output...
  1638.     if (options->xmlOutput != 0)
  1639.     {
  1640.         time( &rawtime );
  1641.         timeinfo = gmtime( &rawtime );
  1642.         strftime( datetime, MAXSTRLEN(datetime), "%Y-%m-%d %H:%M:%S +0000", timeinfo);
  1643.  
  1644.         fprintf(options->xmlOutput, " <ssltest host=\"%s\" port=\"%d\" time=\"%s\">\n", options->host, options->port, datetime);
  1645.     }
  1646.  
  1647.     // Test supported ciphers...
  1648.     if (options->quiet == false)
  1649.     {
  1650.         printf("\nTesting SSL server %s on port %d\n\n", options->host, options->port);
  1651.         printf("  Supported Server Cipher(s):\n");
  1652.         if ((options->http == true) && (options->pout == true))
  1653.             printf("|| Status || HTTP Code || Version || Bits || Cipher ||\n");
  1654.         else if (options->pout == true)
  1655.             printf("|| Status || Version || Bits || Cipher ||\n");
  1656.     }
  1657.     sslCipherPointer = options->ciphers;
  1658.     while ((sslCipherPointer != 0) && (status == true))
  1659.     {
  1660.  
  1661.         // Setup Context Object...
  1662.         options->ctx = SSL_CTX_new(sslCipherPointer->sslMethod);
  1663.         if (options->ctx != NULL)
  1664.         {
  1665.  
  1666.             // SSL implementation bugs/workaround
  1667.             if (options->sslbugs)
  1668.                 SSL_CTX_set_options(options->ctx, SSL_OP_ALL | 0);
  1669.             else
  1670.                 SSL_CTX_set_options(options->ctx, 0);
  1671.  
  1672.             // Load Certs if required...
  1673.             if ((options->clientCertsFile != 0) || (options->privateKeyFile != 0))
  1674.                 status = loadCerts(options);
  1675.  
  1676.             // Test
  1677.             if (status == true)
  1678.                 status = testCipher(options, sslCipherPointer);
  1679.  
  1680.             // Free CTX Object
  1681.             SSL_CTX_free(options->ctx);
  1682.         }
  1683.    
  1684.         // Error Creating Context Object
  1685.         else
  1686.         {
  1687.             status = false;
  1688.             fprintf(stderr, "ERROR: Could not create CTX object.\n");
  1689.         }
  1690.  
  1691.         sslCipherPointer = sslCipherPointer->next;
  1692.     }
  1693.  
  1694.     if (status == true)
  1695.     {
  1696.         // Test prefered ciphers...
  1697.         if (options->quiet == false)
  1698.         {
  1699.             printf("\n  Prefered Server Cipher(s):\n");
  1700.             if (options->pout == true)
  1701.                 printf("|| Version || Bits || Cipher ||\n");
  1702.         }
  1703.         switch (options->sslVersion)
  1704.         {
  1705.             case ssl_all:
  1706.                 status = defaultCipher(options, SSLv2_client_method());
  1707.                 if (status != false) status = defaultCipher(options, SSLv3_client_method());
  1708.                 if (status != false) status = defaultCipher(options, TLSv1_client_method());
  1709.                 if (status != false) status = defaultCipher(options, TLSv1_1_client_method());
  1710.                 if (status != false) status = defaultCipher(options, TLSv1_2_client_method());
  1711.                 break;
  1712.             case ssl_v2:
  1713.                 status = defaultCipher(options, SSLv2_client_method());
  1714.                 break;
  1715.             case ssl_v3:
  1716.                 status = defaultCipher(options, SSLv3_client_method());
  1717.                 break;
  1718.             case tls_v1:
  1719.                 status = defaultCipher(options, TLSv1_client_method());
  1720.                 if (status != false) status = defaultCipher(options, TLSv1_1_client_method());
  1721.                 if (status != false) status = defaultCipher(options, TLSv1_2_client_method());
  1722.                 break;
  1723.         }
  1724.     }
  1725.  
  1726.     if (status == true)
  1727.     {
  1728.         status = getCertificate(options);
  1729.     }
  1730.  
  1731.     if (status == true)
  1732.     {
  1733.       status = testRenegotiation(options, TLSv1_2_client_method());
  1734.       if (status == false) status = testRenegotiation(options, TLSv1_1_client_method());
  1735.       if (status == false) status = testRenegotiation(options, TLSv1_client_method());
  1736.     }
  1737.  
  1738.     if (options->xmlOutput != NULL)
  1739.         fprintf(options->xmlOutput, " </ssltest>\n");
  1740.  
  1741.     // Return status...
  1742.     return status;
  1743. }
  1744.  
  1745.  
  1746. int main(int argc, char *argv[])
  1747. {
  1748.     // Variables...
  1749.     struct sslCheckOptions options;
  1750.     struct sslCipher *sslCipherPointer;
  1751.     int status;
  1752.     int argLoop;
  1753.     int tempInt;
  1754.     int maxSize;
  1755.     int xmlArg;
  1756.     int mode = mode_help;
  1757.     FILE *targetsFile;
  1758.     char line[1024];
  1759.    
  1760.     // Init...
  1761.     memset(&options, 0, sizeof(struct sslCheckOptions));
  1762.     options.port = 443;
  1763.     xmlArg = 0;
  1764.     strcpy(options.host, "127.0.0.1");
  1765.     options.noFailed = false;
  1766.     options.starttls = false;
  1767.     options.sslVersion = ssl_all;
  1768.     options.pout = false;
  1769.     options.quiet = false;
  1770.  
  1771.     SSL_library_init();
  1772.  
  1773.     // Get program parameters
  1774.     for (argLoop = 1; argLoop < argc; argLoop++)
  1775.     {
  1776.         // Help
  1777.         if (strcmp("--help", argv[argLoop]) == 0)
  1778.             mode = mode_help;
  1779.  
  1780.         // targets
  1781.         else if ((strncmp("--targets=", argv[argLoop], 10) == 0) && (strlen(argv[argLoop]) > 10))
  1782.         {
  1783.             mode = mode_multiple;
  1784.             options.targets = argLoop;
  1785.         }
  1786.  
  1787.         // Show only supported
  1788.         else if (strcmp("--no-failed", argv[argLoop]) == 0)
  1789.             options.noFailed = true;
  1790.  
  1791.         // Version
  1792.         else if (strcmp("--version", argv[argLoop]) == 0)
  1793.             mode = mode_version;
  1794.  
  1795.         // XML Output
  1796.         else if (strncmp("--xml=", argv[argLoop], 6) == 0)
  1797.             xmlArg = argLoop;
  1798.  
  1799.         // P Output
  1800.         else if (strcmp("-p", argv[argLoop]) == 0)
  1801.             options.pout = true;
  1802.  
  1803.         // Quiet output
  1804.         else if (strcmp("--quiet", argv[argLoop]) == 0)
  1805.             options.quiet = true;
  1806.  
  1807.         // Client Certificates
  1808.         else if (strncmp("--certs=", argv[argLoop], 8) == 0)
  1809.             options.clientCertsFile = argv[argLoop] +8;
  1810.  
  1811.         // CA Certificates
  1812.         else if (strncmp("--cafile=", argv[argLoop], 9) == 0)
  1813.             options.CAfile = argv[argLoop] +9;
  1814.  
  1815.         else if (strncmp("--capath=", argv[argLoop], 9) == 0)
  1816.             options.CApath = argv[argLoop] +9;
  1817.  
  1818.         // Private Key File
  1819.         else if (strncmp("--pk=", argv[argLoop], 5) == 0)
  1820.             options.privateKeyFile = argv[argLoop] +5;
  1821.  
  1822.         // Private Key Password
  1823.         else if (strncmp("--pkpass=", argv[argLoop], 9) == 0)
  1824.             options.privateKeyPassword = argv[argLoop] +9;
  1825.  
  1826.         // StartTLS...
  1827.         else if (strcmp("--starttls", argv[argLoop]) == 0)
  1828.         {
  1829.             options.sslVersion = tls_v1;
  1830.             options.starttls = true;
  1831.             options.port = 25; // default to SMTP when you want to use STARTTLS
  1832.         }
  1833.  
  1834.         // SSL v2 only...
  1835.         else if (strcmp("--ssl2", argv[argLoop]) == 0)
  1836.             options.sslVersion = ssl_v2;
  1837.  
  1838.         // SSL v3 only...
  1839.         else if (strcmp("--ssl3", argv[argLoop]) == 0)
  1840.             options.sslVersion = ssl_v3;
  1841.  
  1842.         // TLS v1 only...
  1843.         else if (strcmp("--tls1", argv[argLoop]) == 0)
  1844.             options.sslVersion = tls_v1;
  1845.  
  1846.         // SSL Bugs...
  1847.         else if (strcmp("--bugs", argv[argLoop]) == 0)
  1848.             options.sslbugs = 1;
  1849.  
  1850.         // SSL HTTP Get...
  1851.         else if (strcmp("--http", argv[argLoop]) == 0)
  1852.             options.http = 1;
  1853.  
  1854.         // Host (maybe port too)...
  1855.         else if (argLoop + 1 == argc)
  1856.         {
  1857.             mode = mode_single;
  1858.  
  1859.             // Get host...
  1860.             tempInt = 0;
  1861.             maxSize = strlen(argv[argLoop]);
  1862.             while ((argv[argLoop][tempInt] != 0) && (argv[argLoop][tempInt] != ':'))
  1863.                 tempInt++;
  1864.             argv[argLoop][tempInt] = 0;
  1865.             strncpy(options.host, argv[argLoop], MAXSTRLEN(options.host));
  1866.  
  1867.             // Get port (if it exists)...
  1868.             tempInt++;
  1869.             if (tempInt < maxSize)
  1870.                 options.port = atoi(argv[argLoop] + tempInt);
  1871.         }
  1872.  
  1873.         // Not too sure what the user is doing...
  1874.         else
  1875.             mode = mode_help;
  1876.     }
  1877.  
  1878.     // Open XML file output...
  1879.     if ((xmlArg > 0) && (mode != mode_help))
  1880.     {
  1881.         if (strncmp("stdout",argv[xmlArg] + 6, 6) == 0)
  1882.         {
  1883.             options.xmlOutput = stdout;
  1884.         }
  1885.         else {
  1886.             options.xmlOutput = fopen(argv[xmlArg] + 6, "w");
  1887.         }
  1888.         if (options.xmlOutput == NULL)
  1889.         {
  1890.             fprintf(stderr, "ERROR: Could not open XML output file %s.\n", argv[xmlArg] + 6);
  1891.             exit(0);
  1892.         }
  1893.        
  1894.         // Output file header...
  1895.         fprintf(options.xmlOutput, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document title=\"SSLScan Results\" version=\"%s\" web=\"http://www.titania.co.uk\">\n", xml_version);
  1896.     }
  1897.  
  1898.     switch (mode)
  1899.     {
  1900.         case mode_version:
  1901.             printf("%s", program_version);
  1902.             break;
  1903.  
  1904.         case mode_help:
  1905.             // Program version banner...
  1906.             printf("%s\n", program_banner);
  1907.             printf("SSLScan is a fast SSL port scanner. SSLScan connects to SSL\n");
  1908.             printf("ports and determines what  ciphers are supported, which are\n");
  1909.             printf("the servers  prefered  ciphers,  which  SSL  protocols  are\n");
  1910.             printf("supported  and   returns  the   SSL   certificate.   Client\n");
  1911.             printf("certificates /  private key can be configured and output is\n");
  1912.             printf("to text / XML.\n\n");
  1913.             printf("Command:\n");
  1914.             printf("  %s [Options] [host:port | host]\n\n", argv[0]);
  1915.             printf("Options:\n");
  1916.             printf("  --targets=<file>     A file containing a list of hosts to\n");
  1917.             printf("                       check.  Hosts can  be supplied  with\n");
  1918.             printf("                       ports (i.e. host:port).\n");
  1919.             printf("  --no-failed          List only accepted ciphers  (default\n");
  1920.             printf("                       is to listing all ciphers).\n");
  1921.             printf("  --ssl2               Only check SSLv2 ciphers.\n");
  1922.             printf("  --ssl3               Only check SSLv3 ciphers.\n");
  1923.             printf("  --tls1               Only check TLSv1 ciphers.\n");
  1924.             printf("  --pk=<file>          A file containing the private key or\n");
  1925.             printf("                       a PKCS#12  file containing a private\n");
  1926.             printf("                       key/certificate pair (as produced by\n");
  1927.             printf("                       MSIE and Netscape).\n");
  1928.             printf("  --pkpass=<password>  The password for the private  key or\n");
  1929.             printf("                       PKCS#12 file.\n");
  1930.             printf("  --certs=<file>       A file containing PEM/ASN1 formatted\n");
  1931.             printf("                       client certificates.\n");
  1932.             printf("  --cafile=<file>      A file containing PEM/ASN1 formatted\n");
  1933.             printf("                       CA certificates.\n");
  1934.             printf("  --capath=<path>      A path containing PEM/ASN1 formatted\n");
  1935.             printf("                       CA certificates.\n");
  1936.             printf("  --starttls           If a STARTTLS is required to kick an\n");
  1937.             printf("                       SMTP service into action.\n");
  1938.             printf("  --http               Test a HTTP connection.\n");
  1939.             printf("  --bugs               Enable SSL implementation  bug work-\n");
  1940.             printf("                       arounds.\n");
  1941.             printf("  --xml=<file>         Output results to an XML file. Use \"stdout\"\n");
  1942.             printf("                           if you want to output XML to the console.\n");
  1943.             printf("  --version            Display the program version.\n");
  1944.             printf("  --quiet              Be quiet\n");
  1945.             printf("  --help               Display the  help text  you are  now\n");
  1946.             printf("                       reading.\n");
  1947.             printf("Example:\n");
  1948.             printf("  %s 127.0.0.1\n\n", argv[0]);
  1949.             break;
  1950.  
  1951.         // Check a single host/port ciphers...
  1952.         case mode_single:
  1953.         case mode_multiple:
  1954.             if (options.quiet == false)
  1955.                 printf("%s", program_banner);
  1956.  
  1957.             SSLeay_add_all_algorithms();
  1958.             ERR_load_crypto_strings();
  1959.  
  1960.             // Build a list of ciphers...
  1961.             switch (options.sslVersion)
  1962.             {
  1963.                 case ssl_all:
  1964.                     populateCipherList(&options, TLSv1_2_client_method());
  1965.                     populateCipherList(&options, TLSv1_1_client_method());
  1966.                     populateCipherList(&options, TLSv1_client_method());
  1967.                     populateCipherList(&options, SSLv3_client_method());
  1968.                     populateCipherList(&options, SSLv2_client_method());
  1969.                     break;
  1970.                 case ssl_v2:
  1971.                     populateCipherList(&options, SSLv2_client_method());
  1972.                     break;
  1973.                 case ssl_v3:
  1974.                     populateCipherList(&options, SSLv3_client_method());
  1975.                     break;
  1976.                 case tls_v1:
  1977.                     populateCipherList(&options, TLSv1_2_client_method());
  1978.                     populateCipherList(&options, TLSv1_1_client_method());
  1979.                     populateCipherList(&options, TLSv1_client_method());
  1980.                     break;
  1981.             }
  1982.  
  1983.             // Do the testing...
  1984.             if (mode == mode_single)
  1985.             {
  1986.                 status = testHost(&options);
  1987.             }
  1988.             else
  1989.             {
  1990.                 if (fileExists(argv[options.targets] + 10) == true)
  1991.                 {
  1992.                     // Open targets file...
  1993.                     targetsFile = fopen(argv[options.targets] + 10, "r");
  1994.                     if (targetsFile == NULL)
  1995.                         fprintf(stderr, "ERROR: Could not open targets file %s.\n", argv[options.targets] + 10);
  1996.                     else
  1997.                     {
  1998.                         readLine(targetsFile, line, sizeof(line));
  1999.                         while (feof(targetsFile) == 0)
  2000.                         {
  2001.                             if (strlen(line) != 0)
  2002.                             {
  2003.                                 // Get host...
  2004.                                 tempInt = 0;
  2005.                                 while ((line[tempInt] != 0) && (line[tempInt] != ':'))
  2006.                                     tempInt++;
  2007.                                 line[tempInt] = 0;
  2008.                                 strncpy(options.host, line, MAXSTRLEN(options.host));
  2009.  
  2010.                                 // Get port (if it exists)...
  2011.                                 tempInt++;
  2012.                                 if (strlen(line + tempInt) > 0)
  2013.                                     options.port = atoi(line + tempInt);
  2014.  
  2015.                                 // Test the host...
  2016.                                 status = testHost(&options);
  2017.                             }
  2018.                             readLine(targetsFile, line, sizeof(line));
  2019.                         }
  2020.                     }
  2021.                 }
  2022.                 else
  2023.                     fprintf(stderr, "ERROR: Targets file %s does not exist.\n", argv[options.targets] + 10);
  2024.             }
  2025.    
  2026.             // Free Structures
  2027.             while (options.ciphers != 0)
  2028.             {
  2029.                 sslCipherPointer = options.ciphers->next;
  2030.                 free(options.ciphers);
  2031.                 options.ciphers = sslCipherPointer;
  2032.             }
  2033.             break;
  2034.     }
  2035.  
  2036.     // Close XML file, if required...
  2037.     if ((xmlArg > 0) && (mode != mode_help))
  2038.     {
  2039.         fprintf(options.xmlOutput, "</document>\n");
  2040.         fclose(options.xmlOutput);
  2041.     }
  2042.  
  2043.     return 0;
  2044. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement