mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-10-21 14:09:27 +00:00
feat(real-world-vfc-slice): add labeled OpenSSL/Firefox/Chromium/curl pair corpus
Harvest 176 isolated vuln-vs-fix functions (109 CVEs, 352 training rows) into benchmarks/pairs/vfc with provenance and a JSONL training manifest. Score the slice as an honesty dashboard (ousast pairs --slice vfc); keep the pair gate on the local fixtures only.
This commit is contained in:
@@ -0,0 +1,504 @@
|
||||
/* Provenance: curl/curl create_conn (fixed).
|
||||
* repo: curl/curl
|
||||
* commit: 5ea3145850ebff1dc2b13d17440300a01ca38161
|
||||
* parent: fd9b40bf8dfd43edcbc0d254d613d95a11061c05
|
||||
* commit_url: https://github.com/curl/curl/commit/5ea3145850ebff1dc2b13d17440300a01ca38161
|
||||
* cve: CVE-2021-22924
|
||||
* license: curl
|
||||
* function: create_conn
|
||||
* relpath: lib/url.c
|
||||
*/
|
||||
|
||||
* create_conn() sets up a new connectdata struct, or re-uses an already
|
||||
* existing one, and resolves host name.
|
||||
*
|
||||
* if this function returns CURLE_OK and *async is set to TRUE, the resolve
|
||||
* response will be coming asynchronously. If *async is FALSE, the name is
|
||||
* already resolved.
|
||||
*
|
||||
* @param data The sessionhandle pointer
|
||||
* @param in_connect is set to the next connection data pointer
|
||||
* @param async is set TRUE when an async DNS resolution is pending
|
||||
* @see Curl_setup_conn()
|
||||
*
|
||||
*/
|
||||
|
||||
static CURLcode create_conn(struct Curl_easy *data,
|
||||
struct connectdata **in_connect,
|
||||
bool *async)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct connectdata *conn;
|
||||
struct connectdata *conn_temp = NULL;
|
||||
bool reuse;
|
||||
bool connections_available = TRUE;
|
||||
bool force_reuse = FALSE;
|
||||
bool waitpipe = FALSE;
|
||||
size_t max_host_connections = Curl_multi_max_host_connections(data->multi);
|
||||
size_t max_total_connections = Curl_multi_max_total_connections(data->multi);
|
||||
|
||||
*async = FALSE;
|
||||
*in_connect = NULL;
|
||||
|
||||
/*************************************************************
|
||||
* Check input data
|
||||
*************************************************************/
|
||||
if(!data->state.url) {
|
||||
result = CURLE_URL_MALFORMAT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* First, split up the current URL in parts so that we can use the
|
||||
parts for checking against the already present connections. In order
|
||||
to not have to modify everything at once, we allocate a temporary
|
||||
connection data struct and fill in for comparison purposes. */
|
||||
conn = allocate_conn(data);
|
||||
|
||||
if(!conn) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* We must set the return variable as soon as possible, so that our
|
||||
parent can cleanup any possible allocs we may have done before
|
||||
any failure */
|
||||
*in_connect = conn;
|
||||
|
||||
result = parseurlandfillconn(data, conn);
|
||||
if(result)
|
||||
goto out;
|
||||
|
||||
if(data->set.str[STRING_SASL_AUTHZID]) {
|
||||
conn->sasl_authzid = strdup(data->set.str[STRING_SASL_AUTHZID]);
|
||||
if(!conn->sasl_authzid) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_UNIX_SOCKETS
|
||||
if(data->set.str[STRING_UNIX_SOCKET_PATH]) {
|
||||
conn->unix_domain_socket = strdup(data->set.str[STRING_UNIX_SOCKET_PATH]);
|
||||
if(!conn->unix_domain_socket) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
conn->bits.abstract_unix_socket = data->set.abstract_unix_socket;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* After the unix socket init but before the proxy vars are used, parse and
|
||||
initialize the proxy vars */
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
result = create_conn_helper_init_proxy(data, conn);
|
||||
if(result)
|
||||
goto out;
|
||||
|
||||
/*************************************************************
|
||||
* If the protocol is using SSL and HTTP proxy is used, we set
|
||||
* the tunnel_proxy bit.
|
||||
*************************************************************/
|
||||
if((conn->given->flags&PROTOPT_SSL) && conn->bits.httpproxy)
|
||||
conn->bits.tunnel_proxy = TRUE;
|
||||
#endif
|
||||
|
||||
/*************************************************************
|
||||
* Figure out the remote port number and fix it in the URL
|
||||
*************************************************************/
|
||||
result = parse_remote_port(data, conn);
|
||||
if(result)
|
||||
goto out;
|
||||
|
||||
/* Check for overridden login details and set them accordingly so that
|
||||
they are known when protocol->setup_connection is called! */
|
||||
result = override_login(data, conn);
|
||||
if(result)
|
||||
goto out;
|
||||
|
||||
result = set_login(conn); /* default credentials */
|
||||
if(result)
|
||||
goto out;
|
||||
|
||||
/*************************************************************
|
||||
* Process the "connect to" linked list of hostname/port mappings.
|
||||
* Do this after the remote port number has been fixed in the URL.
|
||||
*************************************************************/
|
||||
result = parse_connect_to_slist(data, conn, data->set.connect_to);
|
||||
if(result)
|
||||
goto out;
|
||||
|
||||
/*************************************************************
|
||||
* IDN-convert the hostnames
|
||||
*************************************************************/
|
||||
result = Curl_idnconvert_hostname(data, &conn->host);
|
||||
if(result)
|
||||
goto out;
|
||||
if(conn->bits.conn_to_host) {
|
||||
result = Curl_idnconvert_hostname(data, &conn->conn_to_host);
|
||||
if(result)
|
||||
goto out;
|
||||
}
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
if(conn->bits.httpproxy) {
|
||||
result = Curl_idnconvert_hostname(data, &conn->http_proxy.host);
|
||||
if(result)
|
||||
goto out;
|
||||
}
|
||||
if(conn->bits.socksproxy) {
|
||||
result = Curl_idnconvert_hostname(data, &conn->socks_proxy.host);
|
||||
if(result)
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*************************************************************
|
||||
* Check whether the host and the "connect to host" are equal.
|
||||
* Do this after the hostnames have been IDN-converted.
|
||||
*************************************************************/
|
||||
if(conn->bits.conn_to_host &&
|
||||
strcasecompare(conn->conn_to_host.name, conn->host.name)) {
|
||||
conn->bits.conn_to_host = FALSE;
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
* Check whether the port and the "connect to port" are equal.
|
||||
* Do this after the remote port number has been fixed in the URL.
|
||||
*************************************************************/
|
||||
if(conn->bits.conn_to_port && conn->conn_to_port == conn->remote_port) {
|
||||
conn->bits.conn_to_port = FALSE;
|
||||
}
|
||||
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
/*************************************************************
|
||||
* If the "connect to" feature is used with an HTTP proxy,
|
||||
* we set the tunnel_proxy bit.
|
||||
*************************************************************/
|
||||
if((conn->bits.conn_to_host || conn->bits.conn_to_port) &&
|
||||
conn->bits.httpproxy)
|
||||
conn->bits.tunnel_proxy = TRUE;
|
||||
#endif
|
||||
|
||||
/*************************************************************
|
||||
* Setup internals depending on protocol. Needs to be done after
|
||||
* we figured out what/if proxy to use.
|
||||
*************************************************************/
|
||||
result = setup_connection_internals(data, conn);
|
||||
if(result)
|
||||
goto out;
|
||||
|
||||
conn->recv[FIRSTSOCKET] = Curl_recv_plain;
|
||||
conn->send[FIRSTSOCKET] = Curl_send_plain;
|
||||
conn->recv[SECONDARYSOCKET] = Curl_recv_plain;
|
||||
conn->send[SECONDARYSOCKET] = Curl_send_plain;
|
||||
|
||||
conn->bits.tcp_fastopen = data->set.tcp_fastopen;
|
||||
|
||||
/***********************************************************************
|
||||
* file: is a special case in that it doesn't need a network connection
|
||||
***********************************************************************/
|
||||
#ifndef CURL_DISABLE_FILE
|
||||
if(conn->handler->flags & PROTOPT_NONETWORK) {
|
||||
bool done;
|
||||
/* this is supposed to be the connect function so we better at least check
|
||||
that the file is present here! */
|
||||
DEBUGASSERT(conn->handler->connect_it);
|
||||
Curl_persistconninfo(data, conn, NULL, -1);
|
||||
result = conn->handler->connect_it(data, &done);
|
||||
|
||||
/* Setup a "faked" transfer that'll do nothing */
|
||||
if(!result) {
|
||||
conn->bits.tcpconnect[FIRSTSOCKET] = TRUE; /* we are "connected */
|
||||
|
||||
Curl_attach_connnection(data, conn);
|
||||
result = Curl_conncache_add_conn(data);
|
||||
if(result)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Setup whatever necessary for a resumed transfer
|
||||
*/
|
||||
result = setup_range(data);
|
||||
if(result) {
|
||||
DEBUGASSERT(conn->handler->done);
|
||||
/* we ignore the return code for the protocol-specific DONE */
|
||||
(void)conn->handler->done(data, result, FALSE);
|
||||
goto out;
|
||||
}
|
||||
Curl_setup_transfer(data, -1, -1, FALSE, -1);
|
||||
}
|
||||
|
||||
/* since we skip do_init() */
|
||||
Curl_init_do(data, conn);
|
||||
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Get a cloned copy of the SSL config situation stored in the
|
||||
connection struct. But to get this going nicely, we must first make
|
||||
sure that the strings in the master copy are pointing to the correct
|
||||
strings in the session handle strings array!
|
||||
|
||||
Keep in mind that the pointers in the master copy are pointing to strings
|
||||
that will be freed as part of the Curl_easy struct, but all cloned
|
||||
copies will be separately allocated.
|
||||
*/
|
||||
data->set.ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH];
|
||||
data->set.ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE];
|
||||
data->set.ssl.primary.issuercert = data->set.str[STRING_SSL_ISSUERCERT];
|
||||
data->set.ssl.primary.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT];
|
||||
data->set.ssl.primary.random_file = data->set.str[STRING_SSL_RANDOM_FILE];
|
||||
data->set.ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
|
||||
data->set.ssl.primary.cipher_list =
|
||||
data->set.str[STRING_SSL_CIPHER_LIST];
|
||||
data->set.ssl.primary.cipher_list13 =
|
||||
data->set.str[STRING_SSL_CIPHER13_LIST];
|
||||
data->set.ssl.primary.pinned_key =
|
||||
data->set.str[STRING_SSL_PINNEDPUBLICKEY];
|
||||
data->set.ssl.primary.cert_blob = data->set.blobs[BLOB_CERT];
|
||||
data->set.ssl.primary.ca_info_blob = data->set.blobs[BLOB_CAINFO];
|
||||
data->set.ssl.primary.curves = data->set.str[STRING_SSL_EC_CURVES];
|
||||
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
data->set.proxy_ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY];
|
||||
data->set.proxy_ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_PROXY];
|
||||
data->set.proxy_ssl.primary.random_file =
|
||||
data->set.str[STRING_SSL_RANDOM_FILE];
|
||||
data->set.proxy_ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
|
||||
data->set.proxy_ssl.primary.cipher_list =
|
||||
data->set.str[STRING_SSL_CIPHER_LIST_PROXY];
|
||||
data->set.proxy_ssl.primary.cipher_list13 =
|
||||
data->set.str[STRING_SSL_CIPHER13_LIST_PROXY];
|
||||
data->set.proxy_ssl.primary.pinned_key =
|
||||
data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY];
|
||||
data->set.proxy_ssl.primary.cert_blob = data->set.blobs[BLOB_CERT_PROXY];
|
||||
data->set.proxy_ssl.primary.ca_info_blob =
|
||||
data->set.blobs[BLOB_CAINFO_PROXY];
|
||||
data->set.proxy_ssl.primary.issuercert =
|
||||
data->set.str[STRING_SSL_ISSUERCERT_PROXY];
|
||||
data->set.proxy_ssl.primary.issuercert_blob =
|
||||
data->set.blobs[BLOB_SSL_ISSUERCERT_PROXY];
|
||||
data->set.proxy_ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_PROXY];
|
||||
data->set.proxy_ssl.cert_type = data->set.str[STRING_CERT_TYPE_PROXY];
|
||||
data->set.proxy_ssl.key = data->set.str[STRING_KEY_PROXY];
|
||||
data->set.proxy_ssl.key_type = data->set.str[STRING_KEY_TYPE_PROXY];
|
||||
data->set.proxy_ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_PROXY];
|
||||
data->set.proxy_ssl.primary.clientcert = data->set.str[STRING_CERT_PROXY];
|
||||
data->set.proxy_ssl.key_blob = data->set.blobs[BLOB_KEY_PROXY];
|
||||
#endif
|
||||
data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE];
|
||||
data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE];
|
||||
data->set.ssl.key = data->set.str[STRING_KEY];
|
||||
data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE];
|
||||
data->set.ssl.key_passwd = data->set.str[STRING_KEY_PASSWD];
|
||||
data->set.ssl.primary.clientcert = data->set.str[STRING_CERT];
|
||||
#ifdef USE_TLS_SRP
|
||||
data->set.ssl.username = data->set.str[STRING_TLSAUTH_USERNAME];
|
||||
data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD];
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
data->set.proxy_ssl.username = data->set.str[STRING_TLSAUTH_USERNAME_PROXY];
|
||||
data->set.proxy_ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_PROXY];
|
||||
#endif
|
||||
#endif
|
||||
data->set.ssl.key_blob = data->set.blobs[BLOB_KEY];
|
||||
|
||||
if(!Curl_clone_primary_ssl_config(&data->set.ssl.primary,
|
||||
&conn->ssl_config)) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
if(!Curl_clone_primary_ssl_config(&data->set.proxy_ssl.primary,
|
||||
&conn->proxy_ssl_config)) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
|
||||
prune_dead_connections(data);
|
||||
|
||||
/*************************************************************
|
||||
* Check the current list of connections to see if we can
|
||||
* re-use an already existing one or if we have to create a
|
||||
* new one.
|
||||
*************************************************************/
|
||||
|
||||
DEBUGASSERT(conn->user);
|
||||
DEBUGASSERT(conn->passwd);
|
||||
|
||||
/* reuse_fresh is TRUE if we are told to use a new connection by force, but
|
||||
we only acknowledge this option if this is not a re-used connection
|
||||
already (which happens due to follow-location or during a HTTP
|
||||
authentication phase). CONNECT_ONLY transfers also refuse reuse. */
|
||||
if((data->set.reuse_fresh && !data->state.this_is_a_follow) ||
|
||||
data->set.connect_only)
|
||||
reuse = FALSE;
|
||||
else
|
||||
reuse = ConnectionExists(data, conn, &conn_temp, &force_reuse, &waitpipe);
|
||||
|
||||
if(reuse) {
|
||||
/*
|
||||
* We already have a connection for this, we got the former connection in
|
||||
* the conn_temp variable and thus we need to cleanup the one we just
|
||||
* allocated before we can move along and use the previously existing one.
|
||||
*/
|
||||
reuse_conn(data, conn, conn_temp);
|
||||
#ifdef USE_SSL
|
||||
free(conn->ssl_extra);
|
||||
#endif
|
||||
free(conn); /* we don't need this anymore */
|
||||
conn = conn_temp;
|
||||
*in_connect = conn;
|
||||
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
infof(data, "Re-using existing connection! (#%ld) with %s %s",
|
||||
conn->connection_id,
|
||||
conn->bits.proxy?"proxy":"host",
|
||||
conn->socks_proxy.host.name ? conn->socks_proxy.host.dispname :
|
||||
conn->http_proxy.host.name ? conn->http_proxy.host.dispname :
|
||||
conn->host.dispname);
|
||||
#else
|
||||
infof(data, "Re-using existing connection! (#%ld) with host %s",
|
||||
conn->connection_id, conn->host.dispname);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
/* We have decided that we want a new connection. However, we may not
|
||||
be able to do that if we have reached the limit of how many
|
||||
connections we are allowed to open. */
|
||||
|
||||
if(conn->handler->flags & PROTOPT_ALPN_NPN) {
|
||||
/* The protocol wants it, so set the bits if enabled in the easy handle
|
||||
(default) */
|
||||
if(data->set.ssl_enable_alpn)
|
||||
conn->bits.tls_enable_alpn = TRUE;
|
||||
if(data->set.ssl_enable_npn)
|
||||
conn->bits.tls_enable_npn = TRUE;
|
||||
}
|
||||
|
||||
if(waitpipe)
|
||||
/* There is a connection that *might* become usable for multiplexing
|
||||
"soon", and we wait for that */
|
||||
connections_available = FALSE;
|
||||
else {
|
||||
/* this gets a lock on the conncache */
|
||||
const char *bundlehost;
|
||||
struct connectbundle *bundle =
|
||||
Curl_conncache_find_bundle(data, conn, data->state.conn_cache,
|
||||
&bundlehost);
|
||||
|
||||
if(max_host_connections > 0 && bundle &&
|
||||
(bundle->num_connections >= max_host_connections)) {
|
||||
struct connectdata *conn_candidate;
|
||||
|
||||
/* The bundle is full. Extract the oldest connection. */
|
||||
conn_candidate = Curl_conncache_extract_bundle(data, bundle);
|
||||
CONNCACHE_UNLOCK(data);
|
||||
|
||||
if(conn_candidate)
|
||||
(void)Curl_disconnect(data, conn_candidate, FALSE);
|
||||
else {
|
||||
infof(data, "No more connections allowed to host %s: %zu",
|
||||
bundlehost, max_host_connections);
|
||||
connections_available = FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
CONNCACHE_UNLOCK(data);
|
||||
|
||||
}
|
||||
|
||||
if(connections_available &&
|
||||
(max_total_connections > 0) &&
|
||||
(Curl_conncache_size(data) >= max_total_connections)) {
|
||||
struct connectdata *conn_candidate;
|
||||
|
||||
/* The cache is full. Let's see if we can kill a connection. */
|
||||
conn_candidate = Curl_conncache_extract_oldest(data);
|
||||
if(conn_candidate)
|
||||
(void)Curl_disconnect(data, conn_candidate, FALSE);
|
||||
else {
|
||||
infof(data, "No connections available in cache");
|
||||
connections_available = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if(!connections_available) {
|
||||
infof(data, "No connections available.");
|
||||
|
||||
conn_free(conn);
|
||||
*in_connect = NULL;
|
||||
|
||||
result = CURLE_NO_CONNECTION_AVAILABLE;
|
||||
goto out;
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* This is a brand new connection, so let's store it in the connection
|
||||
* cache of ours!
|
||||
*/
|
||||
Curl_attach_connnection(data, conn);
|
||||
result = Curl_conncache_add_conn(data);
|
||||
if(result)
|
||||
goto out;
|
||||
}
|
||||
|
||||
#if defined(USE_NTLM)
|
||||
/* If NTLM is requested in a part of this connection, make sure we don't
|
||||
assume the state is fine as this is a fresh connection and NTLM is
|
||||
connection based. */
|
||||
if((data->state.authhost.picked & (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
|
||||
data->state.authhost.done) {
|
||||
infof(data, "NTLM picked AND auth done set, clear picked!");
|
||||
data->state.authhost.picked = CURLAUTH_NONE;
|
||||
data->state.authhost.done = FALSE;
|
||||
}
|
||||
|
||||
if((data->state.authproxy.picked & (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
|
||||
data->state.authproxy.done) {
|
||||
infof(data, "NTLM-proxy picked AND auth done set, clear picked!");
|
||||
data->state.authproxy.picked = CURLAUTH_NONE;
|
||||
data->state.authproxy.done = FALSE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Setup and init stuff before DO starts, in preparing for the transfer. */
|
||||
Curl_init_do(data, conn);
|
||||
|
||||
/*
|
||||
* Setup whatever necessary for a resumed transfer
|
||||
*/
|
||||
result = setup_range(data);
|
||||
if(result)
|
||||
goto out;
|
||||
|
||||
/* Continue connectdata initialization here. */
|
||||
|
||||
/*
|
||||
* Inherit the proper values from the urldata struct AFTER we have arranged
|
||||
* the persistent connection stuff
|
||||
*/
|
||||
conn->seek_func = data->set.seek_func;
|
||||
conn->seek_client = data->set.seek_client;
|
||||
|
||||
/*************************************************************
|
||||
* Resolve the address of the server or proxy
|
||||
*************************************************************/
|
||||
result = resolve_server(data, conn, async);
|
||||
|
||||
/* Strip trailing dots. resolve_server copied the name. */
|
||||
strip_trailing_dot(&conn->host);
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
if(conn->bits.httpproxy)
|
||||
strip_trailing_dot(&conn->http_proxy.host);
|
||||
if(conn->bits.socksproxy)
|
||||
strip_trailing_dot(&conn->socks_proxy.host);
|
||||
#endif
|
||||
if(conn->bits.conn_to_host)
|
||||
strip_trailing_dot(&conn->conn_to_host);
|
||||
|
||||
out:
|
||||
return result;
|
||||
}
|
||||
Reference in New Issue
Block a user