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