Unverified Commit 1328f69d authored by Johannes Schindelin's avatar Johannes Schindelin Committed by Daniel Stenberg
Browse files

vtls: introduce curl_global_sslset()



Let's add a compile time safe API to select an SSL backend. This
function needs to be called *before* curl_global_init(), and can be
called only once.

Side note: we do not explicitly test that it is called before
curl_global_init(), but we do verify that it is not called multiple times
(even implicitly).

If SSL is used before the function was called, it will use whatever the
CURL_SSL_BACKEND environment variable says (or default to the first
available SSL backend), and if a subsequent call to
curl_global_sslset() disagrees with the previous choice, it will fail
with CURLSSLSET_TOO_LATE.

The function also accepts an "avail" parameter to point to a (read-only)
NULL-terminated list of available backends. This comes in real handy if
an application wants to let the user choose between whatever SSL backends
the currently available libcurl has to offer: simply call

	curl_global_sslset(-1, NULL, &avail);

which will return CURLSSLSET_UNKNOWN_BACKEND and populate the avail
variable to point to the relevant information to present to the user.

Just like with the HTTP/2 push functions, we have to add the function
declaration of curl_global_sslset() function to the header file
*multi.h* because VMS and OS/400 require a stable order of functions
declared in include/curl/*.h (where the header files are sorted
alphabetically). This looks a bit funny, but it cannot be helped.

Signed-off-by: default avatarJohannes Schindelin <johannes.schindelin@gmx.de>
parent b59288f8
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -690,6 +690,9 @@ CURLSSLBACKEND_SCHANNEL 7.34.0
CURLSSLBACKEND_WOLFSSL          7.49.0
CURLSSLOPT_ALLOW_BEAST          7.25.0
CURLSSLOPT_NO_REVOKE            7.44.0
CURLSSLSET_OK                   7.56.0
CURLSSLSET_UNKNOWN_BACKEND      7.56.0
CURLSSLSET_TOO_LATE             7.56.0
CURLUSESSL_ALL                  7.17.0
CURLUSESSL_CONTROL              7.17.0
CURLUSESSL_NONE                 7.17.0
+0 −5
Original line number Diff line number Diff line
@@ -2540,11 +2540,6 @@ CURL_EXTERN CURLcode curl_easy_pause(CURL *handle, int bitmask);
#define CURLPAUSE_ALL       (CURLPAUSE_RECV|CURLPAUSE_SEND)
#define CURLPAUSE_CONT      (CURLPAUSE_RECV_CONT|CURLPAUSE_SEND_CONT)

typedef struct {
  curl_sslbackend id;
  const char *name;
} curl_ssl_backend;

#ifdef  __cplusplus
}
#endif
+44 −0
Original line number Diff line number Diff line
@@ -432,6 +432,50 @@ typedef int (*curl_push_callback)(CURL *parent,
                                  struct curl_pushheaders *headers,
                                  void *userp);

/*
 * NAME curl_global_sslset()
 *
 * DESCRIPTION
 *
 * When built with multiple SSL backends, curl_global_sslset() allows to
 * choose one. This function can only be called once, and it must be called
 * *before* curl_global_init().
 *
 * The backend can be identified by the id (e.g. CURLSSLBACKEND_OPENSSL). The
 * backend can also be specified via the name parameter (passing -1 as id).
 * If both id and name are specified, the name will be ignored. If neither id
 * nor name are specified, the function will fail with
 * CURLSSLSET_UNKNOWN_BACKEND and set the "avail" pointer to the
 * NULL-terminated list of available backends.
 *
 * Upon success, the function returns CURLSSLSET_OK.
 *
 * If the specified SSL backend is not available, the function returns
 * CURLSSLSET_UNKNOWN_BACKEND and sets the "avail" pointer to a NULL-terminated
 * list of available SSL backends.
 *
 * The SSL backend can be set only once. If it has already been set, a
 * subsequent attempt to change it will result in a CURLSSLSET_TOO_LATE.
 */

typedef struct {
  curl_sslbackend id;
  const char *name;
} curl_ssl_backend;

typedef enum {
  CURLSSLSET_OK = 0,
  CURLSSLSET_UNKNOWN_BACKEND,
  CURLSSLSET_TOO_LATE
} CURLsslset;

CURL_EXTERN CURLsslset curl_global_sslset(curl_sslbackend id, const char *name,
                                          const curl_ssl_backend ***avail);

#ifdef  __cplusplus
}
#endif

#ifdef __cplusplus
} /* end of extern "C" */
#endif
+34 −9
Original line number Diff line number Diff line
@@ -131,13 +131,13 @@ void Curl_free_primary_ssl_config(struct ssl_primary_config* sslc)
}

#ifdef USE_SSL
static int multissl_init(void);
static int multissl_init(const struct Curl_ssl *backend);
#endif

int Curl_ssl_backend(void)
{
#ifdef USE_SSL
  multissl_init();
  multissl_init(NULL);
  return Curl_ssl->info.id;
#else
  return (int)CURLSSLBACKEND_NONE;
@@ -1056,21 +1056,21 @@ CURLcode Curl_none_md5sum(unsigned char *input, size_t inputlen,

static int Curl_multissl_init(void)
{
  if(multissl_init())
  if(multissl_init(NULL))
    return 1;
  return Curl_ssl->init();
}

static size_t Curl_multissl_version(char *buffer, size_t size)
{
  if(multissl_init())
  if(multissl_init(NULL))
    return 0;
  return Curl_ssl->version(buffer, size);
}

static CURLcode Curl_multissl_connect(struct connectdata *conn, int sockindex)
{
  if(multissl_init())
  if(multissl_init(NULL))
    return CURLE_FAILED_INIT;
  return Curl_ssl->connect(conn, sockindex);
}
@@ -1078,7 +1078,7 @@ static CURLcode Curl_multissl_connect(struct connectdata *conn, int sockindex)
static CURLcode Curl_multissl_connect_nonblocking(struct connectdata *conn,
                                                  int sockindex, bool *done)
{
  if(multissl_init())
  if(multissl_init(NULL))
    return CURLE_FAILED_INIT;
  return Curl_ssl->connect_nonblocking(conn, sockindex, done);
}
@@ -1086,14 +1086,14 @@ static CURLcode Curl_multissl_connect_nonblocking(struct connectdata *conn,
static void *Curl_multissl_get_internals(struct ssl_connect_data *connssl,
                                         CURLINFO info)
{
  if(multissl_init())
  if(multissl_init(NULL))
    return NULL;
  return Curl_ssl->get_internals(connssl, info);
}

static void Curl_multissl_close(struct connectdata *conn, int sockindex)
{
  if(multissl_init())
  if(multissl_init(NULL))
    return;
  Curl_ssl->close(conn, sockindex);
}
@@ -1167,7 +1167,7 @@ static const struct Curl_ssl *available_backends[] = {
  NULL
};

static int multissl_init(void)
static int multissl_init(const struct Curl_ssl *backend)
{
  const char *env;
  int i;
@@ -1175,6 +1175,11 @@ static int multissl_init(void)
  if(Curl_ssl != &Curl_ssl_multi)
    return 1;

  if(backend) {
    Curl_ssl = backend;
    return 0;
  }

  if(!available_backends[0])
    return 1;

@@ -1191,4 +1196,24 @@ static int multissl_init(void)
  return 0;
}

CURLsslset curl_global_sslset(curl_sslbackend id, const char *name,
                              const curl_ssl_backend ***avail)
{
  int i;

  if(Curl_ssl != &Curl_ssl_multi)
    return id == Curl_ssl->info.id ? CURLSSLSET_OK : CURLSSLSET_TOO_LATE;

  for(i = 0; available_backends[i]; i++)
    if(available_backends[i]->info.id == id ||
       (name && !strcmp(available_backends[i]->info.name, name))) {
      multissl_init(available_backends[i]);
      return CURLSSLSET_OK;
    }

  if(avail)
    *avail = (const curl_ssl_backend **)&available_backends;
  return CURLSSLSET_UNKNOWN_BACKEND;
}

#endif /* USE_SSL */
+1 −0
Original line number Diff line number Diff line
@@ -89,6 +89,7 @@ CURL_EXTERN CURLMcode curl_multi_setopt(CURLM *multi_handle,
CURL_EXTERN CURLMcode curl_multi_assign(CURLM *multi_handle,
CURL_EXTERN char *curl_pushheader_bynum(struct curl_pushheaders *h,
CURL_EXTERN char *curl_pushheader_byname(struct curl_pushheaders *h,
CURL_EXTERN CURLsslset curl_global_sslset(curl_sslbackend id, const char *name,
</stdout>
</verify>