]> granicus.if.org Git - curl/commitdiff
vtls: declare Curl_ssl structs for every SSL backend
authorJohannes Schindelin <johannes.schindelin@gmx.de>
Thu, 22 Jun 2017 14:45:34 +0000 (16:45 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Mon, 28 Aug 2017 12:56:56 +0000 (14:56 +0200)
The idea of introducing the Curl_ssl struct was to unify how the SSL
backends are declared and called. To this end, we now provide an
instance of the Curl_ssl struct for each and every SSL backend.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
22 files changed:
lib/vtls/axtls.c
lib/vtls/axtls.h
lib/vtls/cyassl.c
lib/vtls/cyassl.h
lib/vtls/darwinssl.c
lib/vtls/darwinssl.h
lib/vtls/gskit.c
lib/vtls/gskit.h
lib/vtls/gtls.c
lib/vtls/gtls.h
lib/vtls/mbedtls.c
lib/vtls/mbedtls.h
lib/vtls/nss.c
lib/vtls/nssg.h
lib/vtls/openssl.c
lib/vtls/openssl.h
lib/vtls/polarssl.c
lib/vtls/polarssl.h
lib/vtls/schannel.c
lib/vtls/schannel.h
lib/vtls/vtls.c
lib/vtls/vtls.h

index e063232ea66d205cde7cadae05497b9fcc90ebc0..0430d79a943c83d05edcd44d2c3b3e7f3f6c26cb 100644 (file)
@@ -702,4 +702,26 @@ CURLcode Curl_axtls_random(struct Curl_easy *data,
   return CURLE_OK;
 }
 
+const struct Curl_ssl Curl_ssl_axtls = {
+  "axtls",                        /* name */
+
+  Curl_axtls_init,                /* init */
+  Curl_axtls_cleanup,             /* cleanup */
+  Curl_axtls_version,             /* version */
+  Curl_axtls_check_cxn,           /* check_cxn */
+  Curl_axtls_shutdown,            /* shutdown */
+  Curl_none_data_pending,         /* data_pending */
+  Curl_axtls_random,              /* random */
+  Curl_none_cert_status_request,  /* cert_status_request */
+  Curl_axtls_connect,             /* connect */
+  Curl_axtls_connect_nonblocking, /* connect_nonblocking */
+  Curl_axtls_close,               /* close */
+  Curl_none_close_all,            /* close_all */
+  Curl_axtls_session_free,        /* session_free */
+  Curl_none_set_engine,           /* set_engine */
+  Curl_none_set_engine_default,   /* set_engine_default */
+  Curl_none_engines_list,         /* engines_list */
+  Curl_none_false_start           /* false_start */
+};
+
 #endif /* USE_AXTLS */
index e4c0c1307314a5793f4fd38848e7bf1abae0dc39..71f3c3d1ca4883b997d4c3a6ca0c87c35d6072aa 100644 (file)
@@ -46,6 +46,8 @@ CURLcode Curl_axtls_random(struct Curl_easy *data,
                            unsigned char *entropy,
                            size_t length);
 
+extern const struct Curl_ssl Curl_ssl_axtls;
+
 /* Set the API backend definition to axTLS */
 #define CURL_SSL_BACKEND CURLSSLBACKEND_AXTLS
 
index 01bfdabd1d09243824c6a33af36d15807cd356d4..995cf629c1ad3037f09bf8319098487adfc02204 100644 (file)
@@ -951,4 +951,26 @@ void Curl_cyassl_sha256sum(const unsigned char *tmp, /* input */
   Sha256Final(&SHA256pw, sha256sum);
 }
 
+const struct Curl_ssl Curl_ssl_cyassl = {
+  "cyassl",                        /* name */
+
+  Curl_cyassl_init,                /* init */
+  Curl_none_cleanup,               /* cleanup */
+  Curl_cyassl_version,             /* version */
+  Curl_none_check_cxn,             /* check_cxn */
+  Curl_cyassl_shutdown,            /* shutdown */
+  Curl_cyassl_data_pending,        /* data_pending */
+  Curl_cyassl_random,              /* random */
+  Curl_none_cert_status_request,   /* cert_status_request */
+  Curl_cyassl_connect,             /* connect */
+  Curl_cyassl_connect_nonblocking, /* connect_nonblocking */
+  Curl_cyassl_close,               /* close */
+  Curl_none_close_all,             /* close_all */
+  Curl_cyassl_session_free,        /* session_free */
+  Curl_none_set_engine,            /* set_engine */
+  Curl_none_set_engine_default,    /* set_engine_default */
+  Curl_none_engines_list,          /* engines_list */
+  Curl_none_false_start            /* false_start */
+};
+
 #endif
index f47719e4e73bc25219bc400f6e9443cf9892c830..3e5049c40572d9b8435c7d2d26aff7e1c48fb604 100644 (file)
@@ -59,6 +59,8 @@ void Curl_cyassl_sha256sum(const unsigned char *tmp, /* input */
                      unsigned char *sha256sum, /* output */
                      size_t unused);
 
+extern const struct Curl_ssl Curl_ssl_cyassl;
+
 /* Set the API backend definition to CyaSSL */
 #define CURL_SSL_BACKEND CURLSSLBACKEND_CYASSL
 
index 25e4bc83f5a056c8ae1f14a4bf0dd241ce1d2241..90618bdce9d44901793fdeb929242054f36597d9 100644 (file)
@@ -2856,6 +2856,28 @@ static ssize_t darwinssl_recv(struct connectdata *conn,
   return (ssize_t)processed;
 }
 
+const struct Curl_ssl Curl_ssl_darwinssl = {
+  "darwinssl",                        /* name */
+
+  Curl_none_init,                     /* init */
+  Curl_none_cleanup,                  /* cleanup */
+  Curl_darwinssl_version,             /* version */
+  Curl_darwinssl_check_cxn,           /* check_cxn */
+  Curl_darwinssl_shutdown,            /* shutdown */
+  Curl_darwinssl_data_pending,        /* data_pending */
+  Curl_darwinssl_random,              /* random */
+  Curl_none_cert_status_request,      /* cert_status_request */
+  Curl_darwinssl_connect,             /* connect */
+  Curl_darwinssl_connect_nonblocking, /* connect_nonblocking */
+  Curl_darwinssl_close,               /* close */
+  Curl_none_close_all,                /* close_all */
+  Curl_darwinssl_session_free,        /* session_free */
+  Curl_none_set_engine,               /* set_engine */
+  Curl_none_set_engine_default,       /* set_engine_default */
+  Curl_none_engines_list,             /* engines_list */
+  Curl_darwinssl_false_start          /* false_start */
+};
+
 #ifdef __clang__
 #pragma clang diagnostic pop
 #endif
index 51931ee8fa88354705f0980cd8f04d3617af6b69..687ecb13aad611665c2c63b65c4a2f742160bd9d 100644 (file)
@@ -54,6 +54,8 @@ void Curl_darwinssl_sha256sum(const unsigned char *tmp, /* input */
                               size_t sha256len);
 bool Curl_darwinssl_false_start(void);
 
+extern const struct Curl_ssl Curl_ssl_darwinssl;
+
 /* Set the API backend definition to SecureTransport */
 #define CURL_SSL_BACKEND CURLSSLBACKEND_DARWINSSL
 
index bf75bddc2ce8d734c2e190974d52f99718a42e53..3da7bf2971dbf7911a753d9955685db032587fd9 100644 (file)
@@ -1334,4 +1334,27 @@ int Curl_gskit_check_cxn(struct connectdata *cxn)
   return -1;  /* connection status unknown */
 }
 
+const struct Curl_ssl Curl_ssl_gskit = {
+  "gskit",                        /* name */
+
+  Curl_gskit_init,                /* init */
+  Curl_gskit_cleanup,             /* cleanup */
+  Curl_gskit_version,             /* version */
+  Curl_gskit_check_cxn,           /* check_cxn */
+  Curl_gskit_shutdown,            /* shutdown */
+  Curl_none_data_pending,         /* data_pending */
+  Curl_none_random,               /* random */
+  Curl_none_cert_status_request,  /* cert_status_request */
+  Curl_gskit_connect,             /* connect */
+  Curl_gskit_connect_nonblocking, /* connect_nonblocking */
+  Curl_gskit_close,               /* close */
+  Curl_none_close_all,            /* close_all */
+  /* No session handling for GSKit */
+  Curl_none_session_free,         /* session_free */
+  Curl_none_set_engine,           /* set_engine */
+  Curl_none_set_engine_default,   /* set_engine_default */
+  Curl_none_engines_list,         /* engines_list */
+  Curl_none_false_start           /* false_start */
+};
+
 #endif /* USE_GSKIT */
index 229759217a398c78172359c17d9c8b3c2dc655ba..b329104d584b3c5352d7668e534769d43ecf86e7 100644 (file)
@@ -44,6 +44,8 @@ int Curl_gskit_check_cxn(struct connectdata *cxn);
 /* Support HTTPS-proxy */
 /* TODO: add '#define HTTPS_PROXY_SUPPORT 1' and fix test #1014 (if need) */
 
+extern const struct Curl_ssl Curl_ssl_gskit;
+
 /* Set the API backend definition to GSKit */
 #define CURL_SSL_BACKEND CURLSSLBACKEND_GSKIT
 
index 3889b8e5f095488bab444408146f7ab8f0489830..495c8514d2beb4b95bc97e8387ed48f7e71d788e 100644 (file)
@@ -1785,4 +1785,26 @@ bool Curl_gtls_cert_status_request(void)
 #endif
 }
 
+const struct Curl_ssl Curl_ssl_gnutls = {
+  "gnutls",                      /* name */
+
+  Curl_gtls_init,                /* init */
+  Curl_gtls_cleanup,             /* cleanup */
+  Curl_gtls_version,             /* version */
+  Curl_none_check_cxn,           /* check_cxn */
+  Curl_gtls_shutdown,            /* shutdown */
+  Curl_gtls_data_pending,        /* data_pending */
+  Curl_gtls_random,              /* random */
+  Curl_gtls_cert_status_request, /* cert_status_request */
+  Curl_gtls_connect,             /* connect */
+  Curl_gtls_connect_nonblocking, /* connect_nonblocking */
+  Curl_gtls_close,               /* close */
+  Curl_none_close_all,           /* close_all */
+  Curl_glts_session_free,        /* session_free */
+  Curl_none_set_engine,          /* set_engine */
+  Curl_none_set_engine_default,  /* set_engine_default */
+  Curl_none_engines_list,        /* engines_list */
+  Curl_none_false_start          /* false_start */
+};
+
 #endif /* USE_GNUTLS */
index 3e5d9e0002af5690aa8a3e96ae73e5d201fc003e..24578b06e07e7a48e20cd996ac838adaa05e0a5c 100644 (file)
@@ -60,6 +60,8 @@ bool Curl_gtls_cert_status_request(void);
 /* Support HTTPS-proxy */
 #define HTTPS_PROXY_SUPPORT 1
 
+extern const struct Curl_ssl Curl_ssl_gnutls;
+
 /* Set the API backend definition to GnuTLS */
 #define CURL_SSL_BACKEND CURLSSLBACKEND_GNUTLS
 
index 1de4a878321f139d6f4453550518ae1aac434a5b..2d5e87d0802f1a0ac9423ab22e984e7df74a2d93 100644 (file)
@@ -1007,4 +1007,26 @@ bool Curl_mbedtls_data_pending(const struct connectdata *conn, int sockindex)
   return mbedtls_ssl_get_bytes_avail(&conn->ssl[sockindex].ssl) != 0;
 }
 
+const struct Curl_ssl Curl_ssl_mbedtls = {
+  "mbedtls",                        /* name */
+
+  Curl_mbedtls_init,                /* init */
+  Curl_mbedtls_cleanup,             /* cleanup */
+  Curl_mbedtls_version,             /* version */
+  Curl_none_check_cxn,              /* check_cxn */
+  Curl_none_shutdown,               /* shutdown */
+  Curl_mbedtls_data_pending,        /* data_pending */
+  Curl_mbedtls_random,              /* random */
+  Curl_none_cert_status_request,    /* cert_status_request */
+  Curl_mbedtls_connect,             /* connect */
+  Curl_mbedtls_connect_nonblocking, /* connect_nonblocking */
+  Curl_mbedtls_close,               /* close */
+  Curl_mbedtls_close_all,           /* close_all */
+  Curl_mbedtls_session_free,        /* session_free */
+  Curl_none_set_engine,             /* set_engine */
+  Curl_none_set_engine_default,     /* set_engine_default */
+  Curl_none_engines_list,           /* engines_list */
+  Curl_none_false_start             /* false_start */
+};
+
 #endif /* USE_MBEDTLS */
index a8041bc56dc9d831528da792548be9b5a40637c9..70bbcb58ac8d463b75ff73d13b674af80d425258 100644 (file)
@@ -59,6 +59,8 @@ CURLcode Curl_mbedtls_random(struct Curl_easy *data, unsigned char *entropy,
 /* this backend supports CURLOPT_SSL_CTX_* */
 #define have_curlssl_ssl_ctx 1
 
+extern const struct Curl_ssl Curl_ssl_mbedtls;
+
 /* API setup for mbedTLS */
 #define curlssl_init() Curl_mbedtls_init()
 #define curlssl_cleanup() Curl_mbedtls_cleanup()
index d1711d6a1b6ee73908b0eb46bbaa480a8e2a9dd7..d6797eedfde642fad2b46801f6e4499901ddd76d 100644 (file)
@@ -2322,4 +2322,28 @@ bool Curl_nss_false_start(void)
 #endif
 }
 
+const struct Curl_ssl Curl_ssl_nss = {
+  "nss",                        /* name */
+
+  Curl_nss_init,                /* init */
+  Curl_nss_cleanup,             /* cleanup */
+  Curl_nss_version,             /* version */
+  Curl_nss_check_cxn,           /* check_cxn */
+  /* NSS has no shutdown function provided and thus always fail */
+  Curl_none_shutdown,           /* shutdown */
+  Curl_none_data_pending,       /* data_pending */
+  Curl_nss_random,              /* random */
+  Curl_nss_cert_status_request, /* cert_status_request */
+  Curl_nss_connect,             /* connect */
+  Curl_nss_connect_nonblocking, /* connect_nonblocking */
+  Curl_nss_close,               /* close */
+  Curl_none_close_all,          /* close_all */
+  /* NSS has its own session ID cache */
+  Curl_none_session_free,       /* session_free */
+  Curl_none_set_engine,         /* set_engine */
+  Curl_none_set_engine_default, /* set_engine_default */
+  Curl_none_engines_list,       /* engines_list */
+  Curl_nss_false_start          /* false_start */
+};
+
 #endif /* USE_NSS */
index 8c46929ff2c506c483e23fab9d6cccfc5a49fba8..6117486e29d178452e2990189909c2fec7b12036 100644 (file)
@@ -68,6 +68,8 @@ bool Curl_nss_false_start(void);
 /* Support HTTPS-proxy */
 #define HTTPS_PROXY_SUPPORT 1
 
+extern const struct Curl_ssl Curl_ssl_nss;
+
 /* Set the API backend definition to NSS */
 #define CURL_SSL_BACKEND CURLSSLBACKEND_NSS
 
index 8c1d5a8e55230e41b7b36e83fca4ce6ac2623838..28e31baea0312700f58e6744d4b9f025a9006253 100644 (file)
@@ -3385,4 +3385,27 @@ bool Curl_ossl_cert_status_request(void)
   return FALSE;
 #endif
 }
+
+const struct Curl_ssl Curl_ssl_openssl = {
+  "openssl",                     /* name */
+
+  Curl_ossl_init,                /* init */
+  Curl_ossl_cleanup,             /* cleanup */
+  Curl_ossl_version,             /* version */
+  Curl_ossl_check_cxn,           /* check_cxn */
+  Curl_ossl_shutdown,            /* shutdown */
+  Curl_ossl_data_pending,        /* data_pending */
+  Curl_ossl_random,              /* random */
+  Curl_ossl_cert_status_request, /* cert_status_request */
+  Curl_ossl_connect,             /* connect */
+  Curl_ossl_connect_nonblocking, /* connect_nonblocking */
+  Curl_ossl_close,               /* close */
+  Curl_ossl_close_all,           /* close_all */
+  Curl_ossl_session_free,        /* session_free */
+  Curl_ossl_set_engine,          /* set_engine */
+  Curl_ossl_set_engine_default,  /* set_engine_default */
+  Curl_ossl_engines_list,        /* engines_list */
+  Curl_none_false_start          /* false_start */
+};
+
 #endif /* USE_OPENSSL */
index b9648d5147c9e7a05c31c0d107283ab131414b8a..92d418f8465d771af48eb42be3e8c4e332054606 100644 (file)
@@ -82,6 +82,8 @@ bool Curl_ossl_cert_status_request(void);
 /* Support HTTPS-proxy */
 #define HTTPS_PROXY_SUPPORT 1
 
+extern const struct Curl_ssl Curl_ssl_openssl;
+
 /* Set the API backend definition to OpenSSL */
 #define CURL_SSL_BACKEND CURLSSLBACKEND_OPENSSL
 
index 8b66a247d92e0a34a6599958b30656ed47df021f..8cfbce9bf70c54115517d6acf8348263b01faca6 100644 (file)
@@ -870,4 +870,29 @@ bool Curl_polarssl_data_pending(const struct connectdata *conn, int sockindex)
   return ssl_get_bytes_avail(&conn->ssl[sockindex].ssl) != 0;
 }
 
+const struct Curl_ssl Curl_ssl_polarssl = {
+  "polarssl",                        /* name */
+
+  Curl_polarssl_init,                /* init */
+  Curl_polarssl_cleanup,             /* cleanup */
+  Curl_polarssl_version,             /* version */
+  Curl_none_check_cxn,               /* check_cxn */
+  Curl_none_shutdown,                /* shutdown */
+  Curl_polarssl_data_pending,        /* data_pending */
+  /* This might cause libcurl to use a weeker random!
+   * TODO: use Polarssl's CTR-DRBG or HMAC-DRBG
+  */
+  Curl_none_random,                  /* random */
+  Curl_none_cert_status_request,     /* cert_status_request */
+  Curl_polarssl_connect,             /* connect */
+  Curl_polarssl_connect_nonblocking, /* connect_nonblocking */
+  Curl_polarssl_close,               /* close */
+  Curl_none_close_all,               /* close_all */
+  Curl_polarssl_session_free,        /* session_free */
+  Curl_none_set_engine,              /* set_engine */
+  Curl_none_set_engine_default,      /* set_engine_default */
+  Curl_none_engines_list,            /* engines_list */
+  Curl_none_false_start              /* false_start */
+};
+
 #endif /* USE_POLARSSL */
index c7b184941159e09e2545c26d4d470d8238c6aabe..632377a166272b5f71b143fbb37f107d35a24187 100644 (file)
@@ -47,6 +47,8 @@ void Curl_polarssl_session_free(void *ptr);
 size_t Curl_polarssl_version(char *buffer, size_t size);
 int Curl_polarssl_shutdown(struct connectdata *conn, int sockindex);
 
+extern const struct Curl_ssl Curl_ssl_polarssl;
+
 /* Set the API backend definition to PolarSSL */
 #define CURL_SSL_BACKEND CURLSSLBACKEND_POLARSSL
 
index 988612cd2f9083b1be1d305fbe71e81989228841..3e148efadd833754377f497233ab22fb31e2d003 100644 (file)
@@ -1726,4 +1726,26 @@ static CURLcode verify_certificate(struct connectdata *conn, int sockindex)
 }
 #endif /* _WIN32_WCE */
 
+const struct Curl_ssl Curl_ssl_schannel = {
+  "schannel",                        /* name */
+
+  Curl_schannel_init,                /* init */
+  Curl_schannel_cleanup,             /* cleanup */
+  Curl_schannel_version,             /* version */
+  Curl_none_check_cxn,               /* check_cxn */
+  Curl_schannel_shutdown,            /* shutdown */
+  Curl_schannel_data_pending,        /* data_pending */
+  Curl_schannel_random,              /* random */
+  Curl_none_cert_status_request,     /* cert_status_request */
+  Curl_schannel_connect,             /* connect */
+  Curl_schannel_connect_nonblocking, /* connect_nonblocking */
+  Curl_schannel_close,               /* close */
+  Curl_none_close_all,               /* close_all */
+  Curl_schannel_session_free,        /* session_free */
+  Curl_none_set_engine,              /* set_engine */
+  Curl_none_set_engine_default,      /* set_engine_default */
+  Curl_none_engines_list,            /* engines_list */
+  Curl_none_false_start              /* false_start */
+};
+
 #endif /* USE_SCHANNEL */
index bd12b952d053e64960350056d1d8ef0112f3c942..0ea30c209471544181f962cc5e564ae5f4bb4c0d 100644 (file)
@@ -95,6 +95,8 @@ size_t Curl_schannel_version(char *buffer, size_t size);
 CURLcode Curl_schannel_random(struct Curl_easy *data, unsigned char *entropy,
                               size_t length);
 
+extern const struct Curl_ssl Curl_ssl_schannel;
+
 /* Set the API backend definition to Schannel */
 #define CURL_SSL_BACKEND CURLSSLBACKEND_SCHANNEL
 
index d5d0971c453dc2d0362ce69c525708da313cc263..9c166d25d4c36c2de1af2feda22ad272eba70a01 100644 (file)
@@ -984,4 +984,88 @@ bool Curl_ssl_false_start(void)
 #endif
 }
 
+/*
+ * Default implementations for unsupported functions.
+ */
+
+int Curl_none_init(void)
+{
+  return 1;
+}
+
+void Curl_none_cleanup(void)
+{ }
+
+int Curl_none_shutdown(struct connectdata *conn UNUSED_PARAM,
+                       int sockindex UNUSED_PARAM)
+{
+  (void)conn;
+  (void)sockindex;
+  return 0;
+}
+
+int Curl_none_check_cxn(struct connectdata *conn UNUSED_PARAM)
+{
+  (void)conn;
+  return -1;
+}
+
+CURLcode Curl_none_random(struct Curl_easy *data UNUSED_PARAM,
+                          unsigned char *entropy UNUSED_PARAM,
+                          size_t length UNUSED_PARAM)
+{
+  (void)data;
+  (void)entropy;
+  (void)length;
+  return CURLE_NOT_BUILT_IN;
+}
+
+void Curl_none_close_all(struct Curl_easy *data UNUSED_PARAM)
+{
+  (void)data;
+}
+
+void Curl_none_session_free(void *ptr UNUSED_PARAM)
+{
+  (void)ptr;
+}
+
+bool Curl_none_data_pending(const struct connectdata *conn UNUSED_PARAM,
+                            int connindex UNUSED_PARAM)
+{
+  (void)conn;
+  (void)connindex;
+  return 0;
+}
+
+bool Curl_none_cert_status_request(void)
+{
+  return FALSE;
+}
+
+CURLcode Curl_none_set_engine(struct Curl_easy *data UNUSED_PARAM,
+                              const char *engine UNUSED_PARAM)
+{
+  (void)data;
+  (void)engine;
+  return CURLE_NOT_BUILT_IN;
+}
+
+CURLcode Curl_none_set_engine_default(struct Curl_easy *data UNUSED_PARAM)
+{
+  (void)data;
+  return CURLE_NOT_BUILT_IN;
+}
+
+struct curl_slist *Curl_none_engines_list(struct Curl_easy *data UNUSED_PARAM)
+{
+  (void)data;
+  return (struct curl_slist *)NULL;
+}
+
+bool Curl_none_false_start(void)
+{
+  return FALSE;
+}
+
 #endif /* USE_SSL */
index b4df047717e89c441b8a5b068a5bb1542f0e6165..9093462da1c5605c5b75feaeac57d496e358b68f 100644 (file)
@@ -56,6 +56,21 @@ struct Curl_ssl {
   bool (*false_start)(void);
 };
 
+int Curl_none_init(void);
+void Curl_none_cleanup(void);
+int Curl_none_shutdown(struct connectdata *conn, int sockindex);
+int Curl_none_check_cxn(struct connectdata *conn);
+CURLcode Curl_none_random(struct Curl_easy *data, unsigned char *entropy,
+                          size_t length);
+void Curl_none_close_all(struct Curl_easy *data);
+void Curl_none_session_free(void *ptr);
+bool Curl_none_data_pending(const struct connectdata *conn, int connindex);
+bool Curl_none_cert_status_request(void);
+CURLcode Curl_none_set_engine(struct Curl_easy *data, const char *engine);
+CURLcode Curl_none_set_engine_default(struct Curl_easy *data);
+struct curl_slist *Curl_none_engines_list(struct Curl_easy *data);
+bool Curl_none_false_start(void);
+
 #include "openssl.h"        /* OpenSSL versions */
 #include "gtls.h"           /* GnuTLS versions */
 #include "nssg.h"           /* NSS versions */