- Added X509 CA Path support

diff --git a/ChangeLog b/ChangeLog
index b24009b..4fbd4b6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -19,6 +19,7 @@
    * Added support for Hardware Acceleration hooking in SSL/TLS
    * Added OpenSSL / PolarSSL compatibility script (tests/compat.sh) and
      example application (programs/ssl/o_p_test) (Requires OpenSSL)
+   * Added X509 CA Path support
 
 Changes
    * Removed redundant POLARSSL_DEBUG_MSG define
diff --git a/include/polarssl/x509.h b/include/polarssl/x509.h
index 2cd883f..e0a2776 100644
--- a/include/polarssl/x509.h
+++ b/include/polarssl/x509.h
@@ -457,6 +457,22 @@
 
 /** \ingroup x509_module */
 /**
+ * \brief          Load one or more certificate files from a path and add them
+ *                 to the chained list. Parses permissively. If some
+ *                 certificates can be parsed, the result is the number
+ *                 of failed certificates it encountered. If none complete
+ *                 correctly, the first error is returned.
+ *
+ * \param chain    points to the start of the chain
+ * \param path     directory / folder to read the certificate files from
+ *
+ * \return         0 if all certificates parsed successfully, a positive number
+ *                 if partly successful or a specific X509 or PEM error code
+ */
+int x509parse_crtpath( x509_cert *chain, const char *path );
+
+/** \ingroup x509_module */
+/**
  * \brief          Parse one or more CRLs and add them
  *                 to the chained list
  *
diff --git a/library/x509parse.c b/library/x509parse.c
index f1e98b3..4234dfc 100644
--- a/library/x509parse.c
+++ b/library/x509parse.c
@@ -60,6 +60,10 @@
 
 #if defined(POLARSSL_FS_IO)
 #include <stdio.h>
+#if !defined(_WIN32)
+#include <sys/types.h>
+#include <dirent.h>
+#endif
 #endif
 
 /*
@@ -1860,6 +1864,68 @@
     return( ret );
 }
 
+int x509parse_crtpath( x509_cert *chain, const char *path )
+{
+    int ret = 0;
+#if defined(_WIN32)
+    int t_ret;
+    TCHAR szDir[MAX_PATH];
+    WIN32_FIND_DATA file_data;
+    HANDLE hFind;
+    DWORD dwError = 0;
+
+    StringCchCopy(szDir, MAX_PATH, path);
+    StringCchCat(szDir, MAX_PATH, TEXT("\\*"));
+
+    hFind = FindFirstFile( szDir, &file_data );
+    if (hFind == INVALID_HANDLE_VALUE) 
+        return( POLARSSL_ERR_X509_FILE_IO_ERROR );
+
+    do
+    {
+        if( file_data.dwAttributes & FILE_ATTRIBUTE_DIRECTORY )
+            continue;
+
+        t_ret = x509parse_crtfile( chain, entry_name );
+        if( t_ret < 0 )
+            return( t_ret );
+
+        ret += t_ret;
+    }
+    while( FindNextFile( hFind, &file_data ) != 0 );
+
+    dwError = GetLastError();
+    if (dwError != ERROR_NO_MORE_FILES) 
+        return( POLARSSL_ERR_X509_FILE_IO_ERROR );
+
+    FindClose( hFind );
+#else
+    int t_ret;
+    struct dirent *entry;
+    char entry_name[255];
+    DIR *dir = opendir( path );
+
+    if( dir == NULL)
+        return( POLARSSL_ERR_X509_FILE_IO_ERROR );
+
+    while( ( entry = readdir( dir ) ) != NULL )
+    {
+        if( entry->d_type != DT_REG )
+            continue;
+
+        snprintf( entry_name, sizeof(entry_name), "%s/%s", path, entry->d_name );
+        t_ret = x509parse_crtfile( chain, entry_name );
+        if( t_ret < 0 )
+            return( t_ret );
+
+        ret += t_ret;
+    }
+    closedir( dir );
+#endif
+
+    return( ret );
+}
+
 /*
  * Load one or more CRLs and add them to the chained list
  */
diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c
index f82abe6..8c0a94d 100644
--- a/programs/ssl/ssl_client2.c
+++ b/programs/ssl/ssl_client2.c
@@ -46,6 +46,7 @@
 #define DFL_REQUEST_PAGE        "/"
 #define DFL_DEBUG_LEVEL         0
 #define DFL_CA_FILE             ""
+#define DFL_CA_PATH             ""
 #define DFL_CRT_FILE            ""
 #define DFL_KEY_FILE            ""
 #define DFL_FORCE_CIPHER        0
@@ -62,6 +63,7 @@
     int debug_level;            /* level of debugging                       */
     char *request_page;         /* page on server to request                */
     char *ca_file;              /* the file with the CA certificate(s)      */
+    char *ca_path;              /* the path with the CA certificate(s) reside */
     char *crt_file;             /* the file with the client certificate     */
     char *key_file;             /* the file with the client key             */
     int force_ciphersuite[2];   /* protocol/ciphersuite to use, or all      */
@@ -79,6 +81,7 @@
 #if defined(POLARSSL_FS_IO)
 #define USAGE_IO \
     "    ca_file=%%s          default: \"\" (pre-loaded)\n" \
+    "    ca_path=%%s          default: \"\" (pre-loaded) (overrides ca_file)\n" \
     "    crt_file=%%s         default: \"\" (pre-loaded)\n" \
     "    key_file=%%s         default: \"\" (pre-loaded)\n"
 #else
@@ -164,6 +167,7 @@
     opt.debug_level         = DFL_DEBUG_LEVEL;
     opt.request_page        = DFL_REQUEST_PAGE;
     opt.ca_file             = DFL_CA_FILE;
+    opt.ca_path             = DFL_CA_PATH;
     opt.crt_file            = DFL_CRT_FILE;
     opt.key_file            = DFL_KEY_FILE;
     opt.force_ciphersuite[0]= DFL_FORCE_CIPHER;
@@ -201,6 +205,8 @@
             opt.request_page = q;
         else if( strcmp( p, "ca_file" ) == 0 )
             opt.ca_file = q;
+        else if( strcmp( p, "ca_path" ) == 0 )
+            opt.ca_path = q;
         else if( strcmp( p, "crt_file" ) == 0 )
             opt.crt_file = q;
         else if( strcmp( p, "key_file" ) == 0 )
@@ -245,7 +251,9 @@
     fflush( stdout );
 
 #if defined(POLARSSL_FS_IO)
-    if( strlen( opt.ca_file ) )
+    if( strlen( opt.ca_path ) )
+        ret = x509parse_crtpath( &cacert, opt.ca_path );
+    else if( strlen( opt.ca_file ) )
         ret = x509parse_crtfile( &cacert, opt.ca_file );
     else 
 #endif