Add version_suites option to ssl_server2
diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c
index 9d2733c..9e09e6f 100644
--- a/programs/ssl/ssl_server2.c
+++ b/programs/ssl/ssl_server2.c
@@ -79,6 +79,7 @@
 #define DFL_PSK_IDENTITY        "Client_identity"
 #define DFL_PSK_LIST            NULL
 #define DFL_FORCE_CIPHER        0
+#define DFL_VERSION_SUITES      NULL
 #define DFL_RENEGOTIATION       SSL_RENEGOTIATION_DISABLED
 #define DFL_ALLOW_LEGACY        SSL_LEGACY_NO_RENEGOTIATION
 #define DFL_RENEGOTIATE         0
@@ -130,6 +131,7 @@
     const char *psk_identity;   /* the pre-shared key identity              */
     char *psk_list;             /* list of PSK id/key pairs for callback    */
     int force_ciphersuite[2];   /* protocol/ciphersuite to use, or all      */
+    const char *version_suites; /* per-version ciphersuites                 */
     int renegotiation;          /* enable / disable renegotiation           */
     int allow_legacy;           /* allow legacy renegotiation               */
     int renegotiate;            /* attempt renegotiation?                   */
@@ -294,9 +296,12 @@
     "    min_version=%%s      default: \"ssl3\"\n"          \
     "    max_version=%%s      default: \"tls1_2\"\n"        \
     "    force_version=%%s    default: \"\" (none)\n"       \
-    "                        options: ssl3, tls1, tls1_1, tls1_2\n" \
-    "\n"                                                    \
-    "    force_ciphersuite=<name>    default: all enabled\n"\
+    "                        options: ssl3, tls1, tls1_1, tls1_2\n"     \
+    "\n"                                                                \
+    "    version_suites=a,b,c,d      per-version ciphersuites\n"        \
+    "                                in order from ssl3 to tls1_2\n"    \
+    "                                default: all enabled\n"            \
+    "    force_ciphersuite=<name>    default: all enabled\n"            \
     " acceptable ciphersuite names:\n"
 
 #if !defined(POLARSSL_ENTROPY_C) ||  \
@@ -556,6 +561,7 @@
     int ret = 0, len, written, frags;
     int listen_fd;
     int client_fd = -1;
+    int version_suites[4][2];
     unsigned char buf[SSL_MAX_CONTENT_LEN + 1];
 #if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED)
     unsigned char psk[MAX_PSK_LEN];
@@ -657,6 +663,7 @@
     opt.psk_identity        = DFL_PSK_IDENTITY;
     opt.psk_list            = DFL_PSK_LIST;
     opt.force_ciphersuite[0]= DFL_FORCE_CIPHER;
+    opt.version_suites      = DFL_VERSION_SUITES;
     opt.renegotiation       = DFL_RENEGOTIATION;
     opt.allow_legacy        = DFL_ALLOW_LEGACY;
     opt.renegotiate         = DFL_RENEGOTIATE;
@@ -732,6 +739,8 @@
             }
             opt.force_ciphersuite[1] = 0;
         }
+        else if( strcmp( p, "version_suites" ) == 0 )
+            opt.version_suites = q;
         else if( strcmp( p, "renegotiation" ) == 0 )
         {
             opt.renegotiation = (atoi( q )) ? SSL_RENEGOTIATION_ENABLED :
@@ -889,6 +898,47 @@
             opt.min_version = ciphersuite_info->min_minor_ver;
     }
 
+    if( opt.version_suites != NULL )
+    {
+        const char *name[4] = { 0 };
+
+        /* Parse 4-element coma-separated list */
+        for( i = 0, p = (char *) opt.version_suites;
+             i < 4 && *p != '\0';
+             i++ )
+        {
+            name[i] = p;
+
+            /* Terminate the current string and move on to next one */
+            while( *p != ',' && *p != '\0' )
+                p++;
+            if( *p == ',' )
+                *p++ = '\0';
+        }
+
+        if( i != 4 )
+        {
+            printf( "too few values for version_suites\n" );
+            ret = 1;
+            goto exit;
+        }
+
+        memset( version_suites, 0, sizeof( version_suites ) );
+
+        /* Get the suites identifiers from their name */
+        for( i = 0; i < 4; i++ )
+        {
+            version_suites[i][0] = ssl_get_ciphersuite_id( name[i] );
+
+            if( version_suites[i][0] == 0 )
+            {
+                printf( "unknown ciphersuite: '%s'\n", name[i] );
+                ret = 2;
+                goto usage;
+            }
+        }
+    }
+
 #if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED)
     /*
      * Unhexify the pre-shared key and parse the list if any given
@@ -1189,6 +1239,22 @@
     if( opt.force_ciphersuite[0] != DFL_FORCE_CIPHER )
         ssl_set_ciphersuites( &ssl, opt.force_ciphersuite );
 
+    if( opt.version_suites != NULL )
+    {
+        ssl_set_ciphersuites_for_version( &ssl, version_suites[0],
+                                          SSL_MAJOR_VERSION_3,
+                                          SSL_MINOR_VERSION_0 );
+        ssl_set_ciphersuites_for_version( &ssl, version_suites[1],
+                                          SSL_MAJOR_VERSION_3,
+                                          SSL_MINOR_VERSION_1 );
+        ssl_set_ciphersuites_for_version( &ssl, version_suites[2],
+                                          SSL_MAJOR_VERSION_3,
+                                          SSL_MINOR_VERSION_2 );
+        ssl_set_ciphersuites_for_version( &ssl, version_suites[3],
+                                          SSL_MAJOR_VERSION_3,
+                                          SSL_MINOR_VERSION_3 );
+    }
+
     ssl_set_renegotiation( &ssl, opt.renegotiation );
     ssl_legacy_renegotiation( &ssl, opt.allow_legacy );