113498266Sopenharmony_ci/***************************************************************************
213498266Sopenharmony_ci *                                  _   _ ____  _
313498266Sopenharmony_ci *  Project                     ___| | | |  _ \| |
413498266Sopenharmony_ci *                             / __| | | | |_) | |
513498266Sopenharmony_ci *                            | (__| |_| |  _ <| |___
613498266Sopenharmony_ci *                             \___|\___/|_| \_\_____|
713498266Sopenharmony_ci *
813498266Sopenharmony_ci * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
913498266Sopenharmony_ci *
1013498266Sopenharmony_ci * This software is licensed as described in the file COPYING, which
1113498266Sopenharmony_ci * you should have received as part of this distribution. The terms
1213498266Sopenharmony_ci * are also available at https://curl.se/docs/copyright.html.
1313498266Sopenharmony_ci *
1413498266Sopenharmony_ci * You may opt to use, copy, modify, merge, publish, distribute and/or sell
1513498266Sopenharmony_ci * copies of the Software, and permit persons to whom the Software is
1613498266Sopenharmony_ci * furnished to do so, under the terms of the COPYING file.
1713498266Sopenharmony_ci *
1813498266Sopenharmony_ci * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
1913498266Sopenharmony_ci * KIND, either express or implied.
2013498266Sopenharmony_ci *
2113498266Sopenharmony_ci * SPDX-License-Identifier: curl
2213498266Sopenharmony_ci *
2313498266Sopenharmony_ci ***************************************************************************/
2413498266Sopenharmony_ci
2513498266Sopenharmony_ci#include "curl_setup.h"
2613498266Sopenharmony_ci
2713498266Sopenharmony_ci#include <curl/curl.h>
2813498266Sopenharmony_ci#include "urldata.h"
2913498266Sopenharmony_ci#include "share.h"
3013498266Sopenharmony_ci#include "psl.h"
3113498266Sopenharmony_ci#include "vtls/vtls.h"
3213498266Sopenharmony_ci#include "hsts.h"
3313498266Sopenharmony_ci
3413498266Sopenharmony_ci/* The last 3 #include files should be in this order */
3513498266Sopenharmony_ci#include "curl_printf.h"
3613498266Sopenharmony_ci#include "curl_memory.h"
3713498266Sopenharmony_ci#include "memdebug.h"
3813498266Sopenharmony_ci
3913498266Sopenharmony_cistruct Curl_share *
4013498266Sopenharmony_cicurl_share_init(void)
4113498266Sopenharmony_ci{
4213498266Sopenharmony_ci  struct Curl_share *share = calloc(1, sizeof(struct Curl_share));
4313498266Sopenharmony_ci  if(share) {
4413498266Sopenharmony_ci    share->magic = CURL_GOOD_SHARE;
4513498266Sopenharmony_ci    share->specifier |= (1<<CURL_LOCK_DATA_SHARE);
4613498266Sopenharmony_ci    Curl_init_dnscache(&share->hostcache, 23);
4713498266Sopenharmony_ci  }
4813498266Sopenharmony_ci
4913498266Sopenharmony_ci  return share;
5013498266Sopenharmony_ci}
5113498266Sopenharmony_ci
5213498266Sopenharmony_ci#undef curl_share_setopt
5313498266Sopenharmony_ciCURLSHcode
5413498266Sopenharmony_cicurl_share_setopt(struct Curl_share *share, CURLSHoption option, ...)
5513498266Sopenharmony_ci{
5613498266Sopenharmony_ci  va_list param;
5713498266Sopenharmony_ci  int type;
5813498266Sopenharmony_ci  curl_lock_function lockfunc;
5913498266Sopenharmony_ci  curl_unlock_function unlockfunc;
6013498266Sopenharmony_ci  void *ptr;
6113498266Sopenharmony_ci  CURLSHcode res = CURLSHE_OK;
6213498266Sopenharmony_ci
6313498266Sopenharmony_ci  if(!GOOD_SHARE_HANDLE(share))
6413498266Sopenharmony_ci    return CURLSHE_INVALID;
6513498266Sopenharmony_ci
6613498266Sopenharmony_ci  if(share->dirty)
6713498266Sopenharmony_ci    /* don't allow setting options while one or more handles are already
6813498266Sopenharmony_ci       using this share */
6913498266Sopenharmony_ci    return CURLSHE_IN_USE;
7013498266Sopenharmony_ci
7113498266Sopenharmony_ci  va_start(param, option);
7213498266Sopenharmony_ci
7313498266Sopenharmony_ci  switch(option) {
7413498266Sopenharmony_ci  case CURLSHOPT_SHARE:
7513498266Sopenharmony_ci    /* this is a type this share will share */
7613498266Sopenharmony_ci    type = va_arg(param, int);
7713498266Sopenharmony_ci
7813498266Sopenharmony_ci    switch(type) {
7913498266Sopenharmony_ci    case CURL_LOCK_DATA_DNS:
8013498266Sopenharmony_ci      break;
8113498266Sopenharmony_ci
8213498266Sopenharmony_ci    case CURL_LOCK_DATA_COOKIE:
8313498266Sopenharmony_ci#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
8413498266Sopenharmony_ci      if(!share->cookies) {
8513498266Sopenharmony_ci        share->cookies = Curl_cookie_init(NULL, NULL, NULL, TRUE);
8613498266Sopenharmony_ci        if(!share->cookies)
8713498266Sopenharmony_ci          res = CURLSHE_NOMEM;
8813498266Sopenharmony_ci      }
8913498266Sopenharmony_ci#else   /* CURL_DISABLE_HTTP */
9013498266Sopenharmony_ci      res = CURLSHE_NOT_BUILT_IN;
9113498266Sopenharmony_ci#endif
9213498266Sopenharmony_ci      break;
9313498266Sopenharmony_ci
9413498266Sopenharmony_ci    case CURL_LOCK_DATA_HSTS:
9513498266Sopenharmony_ci#ifndef CURL_DISABLE_HSTS
9613498266Sopenharmony_ci      if(!share->hsts) {
9713498266Sopenharmony_ci        share->hsts = Curl_hsts_init();
9813498266Sopenharmony_ci        if(!share->hsts)
9913498266Sopenharmony_ci          res = CURLSHE_NOMEM;
10013498266Sopenharmony_ci      }
10113498266Sopenharmony_ci#else   /* CURL_DISABLE_HSTS */
10213498266Sopenharmony_ci      res = CURLSHE_NOT_BUILT_IN;
10313498266Sopenharmony_ci#endif
10413498266Sopenharmony_ci      break;
10513498266Sopenharmony_ci
10613498266Sopenharmony_ci    case CURL_LOCK_DATA_SSL_SESSION:
10713498266Sopenharmony_ci#ifdef USE_SSL
10813498266Sopenharmony_ci      if(!share->sslsession) {
10913498266Sopenharmony_ci        share->max_ssl_sessions = 8;
11013498266Sopenharmony_ci        share->sslsession = calloc(share->max_ssl_sessions,
11113498266Sopenharmony_ci                                   sizeof(struct Curl_ssl_session));
11213498266Sopenharmony_ci        share->sessionage = 0;
11313498266Sopenharmony_ci        if(!share->sslsession)
11413498266Sopenharmony_ci          res = CURLSHE_NOMEM;
11513498266Sopenharmony_ci      }
11613498266Sopenharmony_ci#else
11713498266Sopenharmony_ci      res = CURLSHE_NOT_BUILT_IN;
11813498266Sopenharmony_ci#endif
11913498266Sopenharmony_ci      break;
12013498266Sopenharmony_ci
12113498266Sopenharmony_ci    case CURL_LOCK_DATA_CONNECT:
12213498266Sopenharmony_ci      if(Curl_conncache_init(&share->conn_cache, 103))
12313498266Sopenharmony_ci        res = CURLSHE_NOMEM;
12413498266Sopenharmony_ci      break;
12513498266Sopenharmony_ci
12613498266Sopenharmony_ci    case CURL_LOCK_DATA_PSL:
12713498266Sopenharmony_ci#ifndef USE_LIBPSL
12813498266Sopenharmony_ci      res = CURLSHE_NOT_BUILT_IN;
12913498266Sopenharmony_ci#endif
13013498266Sopenharmony_ci      break;
13113498266Sopenharmony_ci
13213498266Sopenharmony_ci    default:
13313498266Sopenharmony_ci      res = CURLSHE_BAD_OPTION;
13413498266Sopenharmony_ci    }
13513498266Sopenharmony_ci    if(!res)
13613498266Sopenharmony_ci      share->specifier |= (unsigned int)(1<<type);
13713498266Sopenharmony_ci    break;
13813498266Sopenharmony_ci
13913498266Sopenharmony_ci  case CURLSHOPT_UNSHARE:
14013498266Sopenharmony_ci    /* this is a type this share will no longer share */
14113498266Sopenharmony_ci    type = va_arg(param, int);
14213498266Sopenharmony_ci    share->specifier &= ~(unsigned int)(1<<type);
14313498266Sopenharmony_ci    switch(type) {
14413498266Sopenharmony_ci    case CURL_LOCK_DATA_DNS:
14513498266Sopenharmony_ci      break;
14613498266Sopenharmony_ci
14713498266Sopenharmony_ci    case CURL_LOCK_DATA_COOKIE:
14813498266Sopenharmony_ci#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
14913498266Sopenharmony_ci      if(share->cookies) {
15013498266Sopenharmony_ci        Curl_cookie_cleanup(share->cookies);
15113498266Sopenharmony_ci        share->cookies = NULL;
15213498266Sopenharmony_ci      }
15313498266Sopenharmony_ci#else   /* CURL_DISABLE_HTTP */
15413498266Sopenharmony_ci      res = CURLSHE_NOT_BUILT_IN;
15513498266Sopenharmony_ci#endif
15613498266Sopenharmony_ci      break;
15713498266Sopenharmony_ci
15813498266Sopenharmony_ci    case CURL_LOCK_DATA_HSTS:
15913498266Sopenharmony_ci#ifndef CURL_DISABLE_HSTS
16013498266Sopenharmony_ci      if(share->hsts) {
16113498266Sopenharmony_ci        Curl_hsts_cleanup(&share->hsts);
16213498266Sopenharmony_ci      }
16313498266Sopenharmony_ci#else   /* CURL_DISABLE_HSTS */
16413498266Sopenharmony_ci      res = CURLSHE_NOT_BUILT_IN;
16513498266Sopenharmony_ci#endif
16613498266Sopenharmony_ci      break;
16713498266Sopenharmony_ci
16813498266Sopenharmony_ci    case CURL_LOCK_DATA_SSL_SESSION:
16913498266Sopenharmony_ci#ifdef USE_SSL
17013498266Sopenharmony_ci      Curl_safefree(share->sslsession);
17113498266Sopenharmony_ci#else
17213498266Sopenharmony_ci      res = CURLSHE_NOT_BUILT_IN;
17313498266Sopenharmony_ci#endif
17413498266Sopenharmony_ci      break;
17513498266Sopenharmony_ci
17613498266Sopenharmony_ci    case CURL_LOCK_DATA_CONNECT:
17713498266Sopenharmony_ci      break;
17813498266Sopenharmony_ci
17913498266Sopenharmony_ci    default:
18013498266Sopenharmony_ci      res = CURLSHE_BAD_OPTION;
18113498266Sopenharmony_ci      break;
18213498266Sopenharmony_ci    }
18313498266Sopenharmony_ci    break;
18413498266Sopenharmony_ci
18513498266Sopenharmony_ci  case CURLSHOPT_LOCKFUNC:
18613498266Sopenharmony_ci    lockfunc = va_arg(param, curl_lock_function);
18713498266Sopenharmony_ci    share->lockfunc = lockfunc;
18813498266Sopenharmony_ci    break;
18913498266Sopenharmony_ci
19013498266Sopenharmony_ci  case CURLSHOPT_UNLOCKFUNC:
19113498266Sopenharmony_ci    unlockfunc = va_arg(param, curl_unlock_function);
19213498266Sopenharmony_ci    share->unlockfunc = unlockfunc;
19313498266Sopenharmony_ci    break;
19413498266Sopenharmony_ci
19513498266Sopenharmony_ci  case CURLSHOPT_USERDATA:
19613498266Sopenharmony_ci    ptr = va_arg(param, void *);
19713498266Sopenharmony_ci    share->clientdata = ptr;
19813498266Sopenharmony_ci    break;
19913498266Sopenharmony_ci
20013498266Sopenharmony_ci  default:
20113498266Sopenharmony_ci    res = CURLSHE_BAD_OPTION;
20213498266Sopenharmony_ci    break;
20313498266Sopenharmony_ci  }
20413498266Sopenharmony_ci
20513498266Sopenharmony_ci  va_end(param);
20613498266Sopenharmony_ci
20713498266Sopenharmony_ci  return res;
20813498266Sopenharmony_ci}
20913498266Sopenharmony_ci
21013498266Sopenharmony_ciCURLSHcode
21113498266Sopenharmony_cicurl_share_cleanup(struct Curl_share *share)
21213498266Sopenharmony_ci{
21313498266Sopenharmony_ci  if(!GOOD_SHARE_HANDLE(share))
21413498266Sopenharmony_ci    return CURLSHE_INVALID;
21513498266Sopenharmony_ci
21613498266Sopenharmony_ci  if(share->lockfunc)
21713498266Sopenharmony_ci    share->lockfunc(NULL, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE,
21813498266Sopenharmony_ci                    share->clientdata);
21913498266Sopenharmony_ci
22013498266Sopenharmony_ci  if(share->dirty) {
22113498266Sopenharmony_ci    if(share->unlockfunc)
22213498266Sopenharmony_ci      share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata);
22313498266Sopenharmony_ci    return CURLSHE_IN_USE;
22413498266Sopenharmony_ci  }
22513498266Sopenharmony_ci
22613498266Sopenharmony_ci  Curl_conncache_close_all_connections(&share->conn_cache);
22713498266Sopenharmony_ci  Curl_conncache_destroy(&share->conn_cache);
22813498266Sopenharmony_ci  Curl_hash_destroy(&share->hostcache);
22913498266Sopenharmony_ci
23013498266Sopenharmony_ci#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
23113498266Sopenharmony_ci  Curl_cookie_cleanup(share->cookies);
23213498266Sopenharmony_ci#endif
23313498266Sopenharmony_ci
23413498266Sopenharmony_ci#ifndef CURL_DISABLE_HSTS
23513498266Sopenharmony_ci  Curl_hsts_cleanup(&share->hsts);
23613498266Sopenharmony_ci#endif
23713498266Sopenharmony_ci
23813498266Sopenharmony_ci#ifdef USE_SSL
23913498266Sopenharmony_ci  if(share->sslsession) {
24013498266Sopenharmony_ci    size_t i;
24113498266Sopenharmony_ci    for(i = 0; i < share->max_ssl_sessions; i++)
24213498266Sopenharmony_ci      Curl_ssl_kill_session(&(share->sslsession[i]));
24313498266Sopenharmony_ci    free(share->sslsession);
24413498266Sopenharmony_ci  }
24513498266Sopenharmony_ci#endif
24613498266Sopenharmony_ci
24713498266Sopenharmony_ci  Curl_psl_destroy(&share->psl);
24813498266Sopenharmony_ci
24913498266Sopenharmony_ci  if(share->unlockfunc)
25013498266Sopenharmony_ci    share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata);
25113498266Sopenharmony_ci  share->magic = 0;
25213498266Sopenharmony_ci  free(share);
25313498266Sopenharmony_ci
25413498266Sopenharmony_ci  return CURLSHE_OK;
25513498266Sopenharmony_ci}
25613498266Sopenharmony_ci
25713498266Sopenharmony_ci
25813498266Sopenharmony_ciCURLSHcode
25913498266Sopenharmony_ciCurl_share_lock(struct Curl_easy *data, curl_lock_data type,
26013498266Sopenharmony_ci                curl_lock_access accesstype)
26113498266Sopenharmony_ci{
26213498266Sopenharmony_ci  struct Curl_share *share = data->share;
26313498266Sopenharmony_ci
26413498266Sopenharmony_ci  if(!share)
26513498266Sopenharmony_ci    return CURLSHE_INVALID;
26613498266Sopenharmony_ci
26713498266Sopenharmony_ci  if(share->specifier & (unsigned int)(1<<type)) {
26813498266Sopenharmony_ci    if(share->lockfunc) /* only call this if set! */
26913498266Sopenharmony_ci      share->lockfunc(data, type, accesstype, share->clientdata);
27013498266Sopenharmony_ci  }
27113498266Sopenharmony_ci  /* else if we don't share this, pretend successful lock */
27213498266Sopenharmony_ci
27313498266Sopenharmony_ci  return CURLSHE_OK;
27413498266Sopenharmony_ci}
27513498266Sopenharmony_ci
27613498266Sopenharmony_ciCURLSHcode
27713498266Sopenharmony_ciCurl_share_unlock(struct Curl_easy *data, curl_lock_data type)
27813498266Sopenharmony_ci{
27913498266Sopenharmony_ci  struct Curl_share *share = data->share;
28013498266Sopenharmony_ci
28113498266Sopenharmony_ci  if(!share)
28213498266Sopenharmony_ci    return CURLSHE_INVALID;
28313498266Sopenharmony_ci
28413498266Sopenharmony_ci  if(share->specifier & (unsigned int)(1<<type)) {
28513498266Sopenharmony_ci    if(share->unlockfunc) /* only call this if set! */
28613498266Sopenharmony_ci      share->unlockfunc (data, type, share->clientdata);
28713498266Sopenharmony_ci  }
28813498266Sopenharmony_ci
28913498266Sopenharmony_ci  return CURLSHE_OK;
29013498266Sopenharmony_ci}
291