mirror of
https://github.com/curl/curl.git
synced 2026-04-11 12:01:42 +08:00
dynbuf: assert init on free
Add a DEBUGASSERT() in Curl_dyn_free() that checks that Curl_dyn_init() has been performed before. Fix code places that did it wrong. Fixes #16725 Closes #16775
This commit is contained in:
parent
cd7eb9e0f2
commit
646b2d6ca2
@ -40,13 +40,15 @@ struct Curl_sec_client_mech {
|
||||
#define AUTH_ERROR 2
|
||||
|
||||
#ifdef HAVE_GSSAPI
|
||||
void Curl_sec_conn_init(struct connectdata *);
|
||||
void Curl_sec_conn_destroy(struct connectdata *);
|
||||
int Curl_sec_read_msg(struct Curl_easy *data, struct connectdata *conn, char *,
|
||||
enum protection_level);
|
||||
void Curl_sec_end(struct connectdata *);
|
||||
CURLcode Curl_sec_login(struct Curl_easy *, struct connectdata *);
|
||||
int Curl_sec_request_prot(struct connectdata *conn, const char *level);
|
||||
#else
|
||||
#define Curl_sec_end(x)
|
||||
#define Curl_sec_conn_init(x) Curl_nop_stmt
|
||||
#define Curl_sec_conn_destroy(x) Curl_nop_stmt
|
||||
#endif
|
||||
|
||||
#endif /* HEADER_CURL_KRB5_H */
|
||||
|
||||
@ -60,6 +60,7 @@ void Curl_dyn_init(struct dynbuf *s, size_t toobig)
|
||||
void Curl_dyn_free(struct dynbuf *s)
|
||||
{
|
||||
DEBUGASSERT(s);
|
||||
DEBUGASSERT(s->init == DYNINIT);
|
||||
Curl_safefree(s->bufr);
|
||||
s->leng = s->allc = 0;
|
||||
}
|
||||
|
||||
18
lib/easy.c
18
lib/easy.c
@ -950,10 +950,6 @@ CURL *curl_easy_duphandle(CURL *d)
|
||||
*/
|
||||
outcurl->set.buffer_size = data->set.buffer_size;
|
||||
|
||||
/* copy all userdefined values */
|
||||
if(dupset(outcurl, data))
|
||||
goto fail;
|
||||
|
||||
Curl_dyn_init(&outcurl->state.headerb, CURL_MAX_HTTP_HEADER);
|
||||
Curl_netrc_init(&outcurl->state.netrc);
|
||||
|
||||
@ -961,6 +957,16 @@ CURL *curl_easy_duphandle(CURL *d)
|
||||
outcurl->state.lastconnect_id = -1;
|
||||
outcurl->state.recent_conn_id = -1;
|
||||
outcurl->id = -1;
|
||||
outcurl->mid = -1;
|
||||
|
||||
#ifndef CURL_DISABLE_HTTP
|
||||
Curl_llist_init(&outcurl->state.httphdrs, NULL);
|
||||
#endif
|
||||
Curl_initinfo(outcurl);
|
||||
|
||||
/* copy all userdefined values */
|
||||
if(dupset(outcurl, data))
|
||||
goto fail;
|
||||
|
||||
outcurl->progress.flags = data->progress.flags;
|
||||
outcurl->progress.callback = data->progress.callback;
|
||||
@ -1054,10 +1060,6 @@ CURL *curl_easy_duphandle(CURL *d)
|
||||
goto fail;
|
||||
}
|
||||
#endif /* USE_ARES */
|
||||
#ifndef CURL_DISABLE_HTTP
|
||||
Curl_llist_init(&outcurl->state.httphdrs, NULL);
|
||||
#endif
|
||||
Curl_initinfo(outcurl);
|
||||
|
||||
outcurl->magic = CURLEASY_MAGIC_NUMBER;
|
||||
|
||||
|
||||
@ -4108,7 +4108,6 @@ static CURLcode ftp_disconnect(struct Curl_easy *data,
|
||||
Curl_safefree(ftpc->prevpath);
|
||||
Curl_safefree(ftpc->server_os);
|
||||
Curl_pp_disconnect(pp);
|
||||
Curl_sec_end(conn);
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -109,9 +109,10 @@ CURLcode Curl_input_negotiate(struct Curl_easy *data, struct connectdata *conn,
|
||||
neg_ctx->sslContext = conn->sslContext;
|
||||
#endif
|
||||
/* Check if the connection is using SSL and get the channel binding data */
|
||||
#if defined(USE_SSL) && defined(HAVE_GSSAPI)
|
||||
#ifdef HAVE_GSSAPI
|
||||
Curl_dyn_init(&neg_ctx->channel_binding_data, SSL_CB_MAX_SIZE + 1);
|
||||
#ifdef USE_SSL
|
||||
if(Curl_conn_is_ssl(conn, FIRSTSOCKET)) {
|
||||
Curl_dyn_init(&neg_ctx->channel_binding_data, SSL_CB_MAX_SIZE + 1);
|
||||
result = Curl_ssl_get_channel_binding(
|
||||
data, FIRSTSOCKET, &neg_ctx->channel_binding_data);
|
||||
if(result) {
|
||||
@ -119,13 +120,14 @@ CURLcode Curl_input_negotiate(struct Curl_easy *data, struct connectdata *conn,
|
||||
return result;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif /* USE_SSL */
|
||||
#endif /* HAVE_GSSAPI */
|
||||
|
||||
/* Initialize the security context and decode our challenge */
|
||||
result = Curl_auth_decode_spnego_message(data, userp, passwdp, service,
|
||||
host, header, neg_ctx);
|
||||
|
||||
#if defined(USE_SSL) && defined(HAVE_GSSAPI)
|
||||
#ifdef HAVE_GSSAPI
|
||||
Curl_dyn_free(&neg_ctx->channel_binding_data);
|
||||
#endif
|
||||
|
||||
|
||||
56
lib/imap.c
56
lib/imap.c
@ -1495,14 +1495,17 @@ static CURLcode imap_connect(struct Curl_easy *data, bool *done)
|
||||
/* We always support persistent connections in IMAP */
|
||||
connkeep(conn, "IMAP default");
|
||||
|
||||
PINGPONG_SETUP(pp, imap_statemachine, imap_endofresp);
|
||||
if(!imapc->initialised) {
|
||||
PINGPONG_SETUP(pp, imap_statemachine, imap_endofresp);
|
||||
|
||||
/* Set the default preferred authentication type and mechanism */
|
||||
imapc->preftype = IMAP_TYPE_ANY;
|
||||
Curl_sasl_init(&imapc->sasl, data, &saslimap);
|
||||
/* Set the default preferred authentication type and mechanism */
|
||||
imapc->preftype = IMAP_TYPE_ANY;
|
||||
Curl_sasl_init(&imapc->sasl, data, &saslimap);
|
||||
|
||||
Curl_dyn_init(&imapc->dyn, DYN_IMAP_CMD);
|
||||
Curl_pp_init(pp);
|
||||
Curl_dyn_init(&imapc->dyn, DYN_IMAP_CMD);
|
||||
Curl_pp_init(pp);
|
||||
imapc->initialised = TRUE;
|
||||
}
|
||||
|
||||
/* Parse the URL options */
|
||||
result = imap_parse_url_options(conn);
|
||||
@ -1692,28 +1695,31 @@ static CURLcode imap_disconnect(struct Curl_easy *data,
|
||||
struct imap_conn *imapc = &conn->proto.imapc;
|
||||
(void)data;
|
||||
|
||||
/* We cannot send quit unconditionally. If this connection is stale or
|
||||
bad in any way, sending quit and waiting around here will make the
|
||||
disconnect wait in vain and cause more problems than we need to. */
|
||||
if(imapc->initialised) {
|
||||
/* We cannot send quit unconditionally. If this connection is stale or
|
||||
bad in any way, sending quit and waiting around here will make the
|
||||
disconnect wait in vain and cause more problems than we need to. */
|
||||
|
||||
/* The IMAP session may or may not have been allocated/setup at this
|
||||
point! */
|
||||
if(!dead_connection && conn->bits.protoconnstart) {
|
||||
if(!imap_perform_logout(data))
|
||||
(void)imap_block_statemach(data, conn, TRUE); /* ignore errors */
|
||||
/* The IMAP session may or may not have been allocated/setup at this
|
||||
point! */
|
||||
if(!dead_connection && conn->bits.protoconnstart) {
|
||||
if(!imap_perform_logout(data))
|
||||
(void)imap_block_statemach(data, conn, TRUE); /* ignore errors */
|
||||
}
|
||||
|
||||
/* Disconnect from the server */
|
||||
Curl_pp_disconnect(&imapc->pp);
|
||||
Curl_dyn_free(&imapc->dyn);
|
||||
|
||||
/* Cleanup the SASL module */
|
||||
Curl_sasl_cleanup(conn, imapc->sasl.authused);
|
||||
|
||||
/* Cleanup our connection based variables */
|
||||
Curl_safefree(imapc->mailbox);
|
||||
Curl_safefree(imapc->mailbox_uidvalidity);
|
||||
memset(imapc, 0, sizeof(*imapc));
|
||||
}
|
||||
|
||||
/* Disconnect from the server */
|
||||
Curl_pp_disconnect(&imapc->pp);
|
||||
Curl_dyn_free(&imapc->dyn);
|
||||
|
||||
/* Cleanup the SASL module */
|
||||
Curl_sasl_cleanup(conn, imapc->sasl.authused);
|
||||
|
||||
/* Cleanup our connection based variables */
|
||||
Curl_safefree(imapc->mailbox);
|
||||
Curl_safefree(imapc->mailbox_uidvalidity);
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -85,6 +85,7 @@ struct imap_conn {
|
||||
BIT(tls_supported); /* StartTLS capability supported by server */
|
||||
BIT(login_disabled); /* LOGIN command disabled by server */
|
||||
BIT(ir_supported); /* Initial response supported by server */
|
||||
BIT(initialised); /* members have been initialised */
|
||||
};
|
||||
|
||||
extern const struct Curl_handler Curl_handler_imap;
|
||||
|
||||
10
lib/krb5.c
10
lib/krb5.c
@ -855,7 +855,6 @@ static CURLcode choose_mech(struct Curl_easy *data, struct connectdata *conn)
|
||||
mech->name);
|
||||
return CURLE_FAILED_INIT;
|
||||
}
|
||||
Curl_dyn_init(&conn->in_buffer.buf, CURL_MAX_INPUT_LENGTH);
|
||||
}
|
||||
|
||||
infof(data, "Trying mechanism %s...", mech->name);
|
||||
@ -914,9 +913,16 @@ Curl_sec_login(struct Curl_easy *data, struct connectdata *conn)
|
||||
return choose_mech(data, conn);
|
||||
}
|
||||
|
||||
void
|
||||
Curl_sec_conn_init(struct connectdata *conn)
|
||||
{
|
||||
Curl_dyn_init(&conn->in_buffer.buf, CURL_MAX_INPUT_LENGTH);
|
||||
conn->in_buffer.index = 0;
|
||||
conn->in_buffer.eof_flag = 0;
|
||||
}
|
||||
|
||||
void
|
||||
Curl_sec_end(struct connectdata *conn)
|
||||
Curl_sec_conn_destroy(struct connectdata *conn)
|
||||
{
|
||||
if(conn->mech && conn->mech->end)
|
||||
conn->mech->end(conn->app_data);
|
||||
|
||||
@ -151,11 +151,13 @@ CURLcode Curl_pp_statemach(struct Curl_easy *data,
|
||||
/* initialize stuff to prepare for reading a fresh new response */
|
||||
void Curl_pp_init(struct pingpong *pp)
|
||||
{
|
||||
DEBUGASSERT(!pp->initialised);
|
||||
pp->nread_resp = 0;
|
||||
pp->response = Curl_now(); /* start response time-out now! */
|
||||
pp->pending_resp = TRUE;
|
||||
Curl_dyn_init(&pp->sendbuf, DYN_PINGPPONG_CMD);
|
||||
Curl_dyn_init(&pp->recvbuf, DYN_PINGPPONG_CMD);
|
||||
pp->initialised = TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
@ -450,8 +452,11 @@ CURLcode Curl_pp_flushsend(struct Curl_easy *data,
|
||||
|
||||
CURLcode Curl_pp_disconnect(struct pingpong *pp)
|
||||
{
|
||||
Curl_dyn_free(&pp->sendbuf);
|
||||
Curl_dyn_free(&pp->recvbuf);
|
||||
if(pp->initialised) {
|
||||
Curl_dyn_free(&pp->sendbuf);
|
||||
Curl_dyn_free(&pp->recvbuf);
|
||||
memset(pp, 0, sizeof(*pp));
|
||||
}
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -70,6 +70,7 @@ struct pingpong {
|
||||
CURLcode (*statemachine)(struct Curl_easy *data, struct connectdata *conn);
|
||||
bool (*endofresp)(struct Curl_easy *data, struct connectdata *conn,
|
||||
const char *ptr, size_t len, int *code);
|
||||
BIT(initialised);
|
||||
};
|
||||
|
||||
#define PINGPONG_SETUP(pp,s,e) \
|
||||
|
||||
13
lib/rtsp.c
13
lib/rtsp.c
@ -130,14 +130,19 @@ const struct Curl_handler Curl_handler_rtsp = {
|
||||
static CURLcode rtsp_setup_connection(struct Curl_easy *data,
|
||||
struct connectdata *conn)
|
||||
{
|
||||
struct rtsp_conn *rtspc = &conn->proto.rtspc;
|
||||
struct RTSP *rtsp;
|
||||
(void)conn;
|
||||
|
||||
if(!rtspc->initialised) {
|
||||
Curl_dyn_init(&rtspc->buf, MAX_RTP_BUFFERSIZE);
|
||||
rtspc->initialised = TRUE;
|
||||
}
|
||||
|
||||
data->req.p.rtsp = rtsp = calloc(1, sizeof(struct RTSP));
|
||||
if(!rtsp)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
Curl_dyn_init(&conn->proto.rtspc.buf, MAX_RTP_BUFFERSIZE);
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
@ -182,9 +187,13 @@ static CURLcode rtsp_connect(struct Curl_easy *data, bool *done)
|
||||
static CURLcode rtsp_disconnect(struct Curl_easy *data,
|
||||
struct connectdata *conn, bool dead)
|
||||
{
|
||||
struct rtsp_conn *rtspc = &conn->proto.rtspc;
|
||||
(void) dead;
|
||||
(void) data;
|
||||
Curl_dyn_free(&conn->proto.rtspc.buf);
|
||||
if(rtspc->initialised) {
|
||||
Curl_dyn_free(&conn->proto.rtspc.buf);
|
||||
rtspc->initialised = FALSE;
|
||||
}
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -53,6 +53,7 @@ struct rtsp_conn {
|
||||
size_t rtp_len;
|
||||
rtp_parse_st state;
|
||||
BIT(in_header);
|
||||
BIT(initialised);
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
45
lib/url.c
45
lib/url.c
@ -90,6 +90,7 @@
|
||||
#include "hsts.h"
|
||||
#include "noproxy.h"
|
||||
#include "cfilters.h"
|
||||
#include "curl_krb5.h"
|
||||
#include "idn.h"
|
||||
|
||||
/* And now for the protocols */
|
||||
@ -506,39 +507,38 @@ CURLcode Curl_open(struct Curl_easy **curl)
|
||||
|
||||
data->magic = CURLEASY_MAGIC_NUMBER;
|
||||
|
||||
Curl_dyn_init(&data->state.headerb, CURL_MAX_HTTP_HEADER);
|
||||
Curl_req_init(&data->req);
|
||||
Curl_initinfo(data);
|
||||
#ifndef CURL_DISABLE_HTTP
|
||||
Curl_llist_init(&data->state.httphdrs, NULL);
|
||||
#endif
|
||||
Curl_netrc_init(&data->state.netrc);
|
||||
|
||||
result = Curl_resolver_init(data, &data->state.async.resolver);
|
||||
if(result) {
|
||||
DEBUGF(fprintf(stderr, "Error: resolver_init failed\n"));
|
||||
Curl_req_free(&data->req, data);
|
||||
free(data);
|
||||
return result;
|
||||
goto out;
|
||||
}
|
||||
|
||||
result = Curl_init_userdefined(data);
|
||||
if(!result) {
|
||||
Curl_dyn_init(&data->state.headerb, CURL_MAX_HTTP_HEADER);
|
||||
Curl_initinfo(data);
|
||||
if(result)
|
||||
goto out;
|
||||
|
||||
/* most recent connection is not yet defined */
|
||||
data->state.lastconnect_id = -1;
|
||||
data->state.recent_conn_id = -1;
|
||||
/* and not assigned an id yet */
|
||||
data->id = -1;
|
||||
data->mid = -1;
|
||||
/* most recent connection is not yet defined */
|
||||
data->state.lastconnect_id = -1;
|
||||
data->state.recent_conn_id = -1;
|
||||
/* and not assigned an id yet */
|
||||
data->id = -1;
|
||||
data->mid = -1;
|
||||
#ifndef CURL_DISABLE_DOH
|
||||
data->set.dohfor_mid = -1;
|
||||
data->set.dohfor_mid = -1;
|
||||
#endif
|
||||
|
||||
data->progress.flags |= PGRS_HIDE;
|
||||
data->state.current_speed = -1; /* init to negative == impossible */
|
||||
#ifndef CURL_DISABLE_HTTP
|
||||
Curl_llist_init(&data->state.httphdrs, NULL);
|
||||
#endif
|
||||
Curl_netrc_init(&data->state.netrc);
|
||||
}
|
||||
data->progress.flags |= PGRS_HIDE;
|
||||
data->state.current_speed = -1; /* init to negative == impossible */
|
||||
|
||||
out:
|
||||
if(result) {
|
||||
Curl_resolver_cleanup(data->state.async.resolver);
|
||||
Curl_dyn_free(&data->state.headerb);
|
||||
@ -578,6 +578,7 @@ void Curl_conn_free(struct Curl_easy *data, struct connectdata *conn)
|
||||
Curl_safefree(conn->http_proxy.host.rawalloc); /* http proxy name buffer */
|
||||
Curl_safefree(conn->socks_proxy.host.rawalloc); /* socks proxy name buffer */
|
||||
#endif
|
||||
Curl_sec_conn_destroy(conn);
|
||||
Curl_safefree(conn->user);
|
||||
Curl_safefree(conn->passwd);
|
||||
Curl_safefree(conn->sasl_authzid);
|
||||
@ -3400,6 +3401,10 @@ static CURLcode create_conn(struct Curl_easy *data,
|
||||
any failure */
|
||||
*in_connect = conn;
|
||||
|
||||
/* Do the unfailable inits first, before checks that may early return */
|
||||
/* GSSAPI related inits */
|
||||
Curl_sec_conn_init(conn);
|
||||
|
||||
result = parseurlandfillconn(data, conn);
|
||||
if(result)
|
||||
goto out;
|
||||
|
||||
@ -156,10 +156,10 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data,
|
||||
}
|
||||
|
||||
/* Set channel binding data if available */
|
||||
if(nego->channel_binding_data.leng > 0) {
|
||||
if(Curl_dyn_len(&nego->channel_binding_data)) {
|
||||
memset(&chan, 0, sizeof(struct gss_channel_bindings_struct));
|
||||
chan.application_data.length = nego->channel_binding_data.leng;
|
||||
chan.application_data.value = nego->channel_binding_data.bufr;
|
||||
chan.application_data.length = Curl_dyn_len(&nego->channel_binding_data);
|
||||
chan.application_data.value = Curl_dyn_ptr(&nego->channel_binding_data);
|
||||
chan_bindings = &chan;
|
||||
}
|
||||
|
||||
|
||||
@ -2086,10 +2086,14 @@ static CURLcode myssh_setup_connection(struct Curl_easy *data,
|
||||
struct SSHPROTO *ssh;
|
||||
struct ssh_conn *sshc = &conn->proto.sshc;
|
||||
|
||||
if(!sshc->initialised) {
|
||||
Curl_dyn_init(&sshc->readdir_buf, CURL_PATH_MAX * 2);
|
||||
sshc->initialised = TRUE;
|
||||
}
|
||||
|
||||
data->req.p.ssh = ssh = calloc(1, sizeof(struct SSHPROTO));
|
||||
if(!ssh)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
Curl_dyn_init(&sshc->readdir_buf, CURL_PATH_MAX * 2);
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
@ -2295,47 +2299,50 @@ static CURLcode myssh_do_it(struct Curl_easy *data, bool *done)
|
||||
static void sshc_cleanup(struct ssh_conn *sshc, struct Curl_easy *data)
|
||||
{
|
||||
(void)data;
|
||||
if(sshc->ssh_session) {
|
||||
ssh_free(sshc->ssh_session);
|
||||
sshc->ssh_session = NULL;
|
||||
}
|
||||
if(sshc->initialised) {
|
||||
if(sshc->ssh_session) {
|
||||
ssh_free(sshc->ssh_session);
|
||||
sshc->ssh_session = NULL;
|
||||
}
|
||||
|
||||
/* worst-case scenario cleanup */
|
||||
DEBUGASSERT(sshc->ssh_session == NULL);
|
||||
DEBUGASSERT(sshc->scp_session == NULL);
|
||||
/* worst-case scenario cleanup */
|
||||
DEBUGASSERT(sshc->ssh_session == NULL);
|
||||
DEBUGASSERT(sshc->scp_session == NULL);
|
||||
|
||||
if(sshc->readdir_tmp) {
|
||||
ssh_string_free_char(sshc->readdir_tmp);
|
||||
sshc->readdir_tmp = NULL;
|
||||
}
|
||||
if(sshc->quote_attrs) {
|
||||
sftp_attributes_free(sshc->quote_attrs);
|
||||
sshc->quote_attrs = NULL;
|
||||
}
|
||||
if(sshc->readdir_attrs) {
|
||||
sftp_attributes_free(sshc->readdir_attrs);
|
||||
sshc->readdir_attrs = NULL;
|
||||
}
|
||||
if(sshc->readdir_link_attrs) {
|
||||
sftp_attributes_free(sshc->readdir_link_attrs);
|
||||
sshc->readdir_link_attrs = NULL;
|
||||
}
|
||||
if(sshc->privkey) {
|
||||
ssh_key_free(sshc->privkey);
|
||||
sshc->privkey = NULL;
|
||||
}
|
||||
if(sshc->pubkey) {
|
||||
ssh_key_free(sshc->pubkey);
|
||||
sshc->pubkey = NULL;
|
||||
}
|
||||
if(sshc->readdir_tmp) {
|
||||
ssh_string_free_char(sshc->readdir_tmp);
|
||||
sshc->readdir_tmp = NULL;
|
||||
}
|
||||
if(sshc->quote_attrs) {
|
||||
sftp_attributes_free(sshc->quote_attrs);
|
||||
sshc->quote_attrs = NULL;
|
||||
}
|
||||
if(sshc->readdir_attrs) {
|
||||
sftp_attributes_free(sshc->readdir_attrs);
|
||||
sshc->readdir_attrs = NULL;
|
||||
}
|
||||
if(sshc->readdir_link_attrs) {
|
||||
sftp_attributes_free(sshc->readdir_link_attrs);
|
||||
sshc->readdir_link_attrs = NULL;
|
||||
}
|
||||
if(sshc->privkey) {
|
||||
ssh_key_free(sshc->privkey);
|
||||
sshc->privkey = NULL;
|
||||
}
|
||||
if(sshc->pubkey) {
|
||||
ssh_key_free(sshc->pubkey);
|
||||
sshc->pubkey = NULL;
|
||||
}
|
||||
|
||||
Curl_safefree(sshc->rsa_pub);
|
||||
Curl_safefree(sshc->rsa);
|
||||
Curl_safefree(sshc->quote_path1);
|
||||
Curl_safefree(sshc->quote_path2);
|
||||
Curl_dyn_free(&sshc->readdir_buf);
|
||||
Curl_safefree(sshc->readdir_linkPath);
|
||||
SSH_STRING_FREE_CHAR(sshc->homedir);
|
||||
Curl_safefree(sshc->rsa_pub);
|
||||
Curl_safefree(sshc->rsa);
|
||||
Curl_safefree(sshc->quote_path1);
|
||||
Curl_safefree(sshc->quote_path2);
|
||||
Curl_dyn_free(&sshc->readdir_buf);
|
||||
Curl_safefree(sshc->readdir_linkPath);
|
||||
SSH_STRING_FREE_CHAR(sshc->homedir);
|
||||
sshc->initialised = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* BLOCKING, but the function is using the state machine so the only reason
|
||||
|
||||
@ -1605,7 +1605,6 @@ static CURLcode sftp_readdir(struct Curl_easy *data,
|
||||
if((sshp->readdir_attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) &&
|
||||
((sshp->readdir_attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
|
||||
LIBSSH2_SFTP_S_IFLNK)) {
|
||||
Curl_dyn_init(&sshp->readdir_link, CURL_PATH_MAX);
|
||||
result = Curl_dyn_addf(&sshp->readdir_link, "%s%s", sshp->path,
|
||||
sshp->readdir_filename);
|
||||
state(data, SSH_SFTP_READDIR_LINK);
|
||||
@ -2430,7 +2429,6 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, bool *block)
|
||||
sshc->actualcode = result ? result : CURLE_SSH;
|
||||
break;
|
||||
}
|
||||
Curl_dyn_init(&sshp->readdir, CURL_PATH_MAX * 2);
|
||||
state(data, SSH_SFTP_READDIR);
|
||||
break;
|
||||
|
||||
@ -3024,13 +3022,23 @@ static CURLcode ssh_block_statemach(struct Curl_easy *data,
|
||||
static CURLcode ssh_setup_connection(struct Curl_easy *data,
|
||||
struct connectdata *conn)
|
||||
{
|
||||
struct ssh_conn *sshc = &conn->proto.sshc;
|
||||
struct SSHPROTO *ssh;
|
||||
(void)conn;
|
||||
|
||||
if(!sshc->initialised) {
|
||||
/* other ssh implementations do something here, let's keep
|
||||
* the initialised flag correct even if this implementation does not. */
|
||||
sshc->initialised = TRUE;
|
||||
}
|
||||
|
||||
data->req.p.ssh = ssh = calloc(1, sizeof(struct SSHPROTO));
|
||||
if(!ssh)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
Curl_dyn_init(&ssh->readdir, CURL_PATH_MAX * 2);
|
||||
Curl_dyn_init(&ssh->readdir_link, CURL_PATH_MAX);
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
@ -3331,60 +3339,62 @@ static int sshc_cleanup(struct ssh_conn *sshc, struct Curl_easy *data,
|
||||
{
|
||||
int rc;
|
||||
|
||||
if(sshc->kh) {
|
||||
libssh2_knownhost_free(sshc->kh);
|
||||
sshc->kh = NULL;
|
||||
if(sshc->initialised) {
|
||||
if(sshc->kh) {
|
||||
libssh2_knownhost_free(sshc->kh);
|
||||
sshc->kh = NULL;
|
||||
}
|
||||
|
||||
if(sshc->ssh_agent) {
|
||||
rc = libssh2_agent_disconnect(sshc->ssh_agent);
|
||||
if(!block && (rc == LIBSSH2_ERROR_EAGAIN)) {
|
||||
return rc;
|
||||
}
|
||||
if(rc < 0) {
|
||||
char *err_msg = NULL;
|
||||
(void)libssh2_session_last_error(sshc->ssh_session,
|
||||
&err_msg, NULL, 0);
|
||||
infof(data, "Failed to disconnect from libssh2 agent: %d %s",
|
||||
rc, err_msg);
|
||||
}
|
||||
libssh2_agent_free(sshc->ssh_agent);
|
||||
sshc->ssh_agent = NULL;
|
||||
|
||||
/* NB: there is no need to free identities, they are part of internal
|
||||
agent stuff */
|
||||
sshc->sshagent_identity = NULL;
|
||||
sshc->sshagent_prev_identity = NULL;
|
||||
}
|
||||
|
||||
if(sshc->ssh_session) {
|
||||
rc = libssh2_session_free(sshc->ssh_session);
|
||||
if(!block && (rc == LIBSSH2_ERROR_EAGAIN)) {
|
||||
return rc;
|
||||
}
|
||||
if(rc < 0) {
|
||||
char *err_msg = NULL;
|
||||
(void)libssh2_session_last_error(sshc->ssh_session,
|
||||
&err_msg, NULL, 0);
|
||||
infof(data, "Failed to free libssh2 session: %d %s", rc, err_msg);
|
||||
}
|
||||
sshc->ssh_session = NULL;
|
||||
}
|
||||
|
||||
/* worst-case scenario cleanup */
|
||||
DEBUGASSERT(sshc->ssh_session == NULL);
|
||||
DEBUGASSERT(sshc->ssh_channel == NULL);
|
||||
DEBUGASSERT(sshc->sftp_session == NULL);
|
||||
DEBUGASSERT(sshc->sftp_handle == NULL);
|
||||
DEBUGASSERT(sshc->kh == NULL);
|
||||
DEBUGASSERT(sshc->ssh_agent == NULL);
|
||||
|
||||
Curl_safefree(sshc->rsa_pub);
|
||||
Curl_safefree(sshc->rsa);
|
||||
Curl_safefree(sshc->quote_path1);
|
||||
Curl_safefree(sshc->quote_path2);
|
||||
Curl_safefree(sshc->homedir);
|
||||
sshc->initialised = FALSE;
|
||||
}
|
||||
|
||||
if(sshc->ssh_agent) {
|
||||
rc = libssh2_agent_disconnect(sshc->ssh_agent);
|
||||
if(!block && (rc == LIBSSH2_ERROR_EAGAIN)) {
|
||||
return rc;
|
||||
}
|
||||
if(rc < 0) {
|
||||
char *err_msg = NULL;
|
||||
(void)libssh2_session_last_error(sshc->ssh_session,
|
||||
&err_msg, NULL, 0);
|
||||
infof(data, "Failed to disconnect from libssh2 agent: %d %s",
|
||||
rc, err_msg);
|
||||
}
|
||||
libssh2_agent_free(sshc->ssh_agent);
|
||||
sshc->ssh_agent = NULL;
|
||||
|
||||
/* NB: there is no need to free identities, they are part of internal
|
||||
agent stuff */
|
||||
sshc->sshagent_identity = NULL;
|
||||
sshc->sshagent_prev_identity = NULL;
|
||||
}
|
||||
|
||||
if(sshc->ssh_session) {
|
||||
rc = libssh2_session_free(sshc->ssh_session);
|
||||
if(!block && (rc == LIBSSH2_ERROR_EAGAIN)) {
|
||||
return rc;
|
||||
}
|
||||
if(rc < 0) {
|
||||
char *err_msg = NULL;
|
||||
(void)libssh2_session_last_error(sshc->ssh_session,
|
||||
&err_msg, NULL, 0);
|
||||
infof(data, "Failed to free libssh2 session: %d %s", rc, err_msg);
|
||||
}
|
||||
sshc->ssh_session = NULL;
|
||||
}
|
||||
|
||||
/* worst-case scenario cleanup */
|
||||
DEBUGASSERT(sshc->ssh_session == NULL);
|
||||
DEBUGASSERT(sshc->ssh_channel == NULL);
|
||||
DEBUGASSERT(sshc->sftp_session == NULL);
|
||||
DEBUGASSERT(sshc->sftp_handle == NULL);
|
||||
DEBUGASSERT(sshc->kh == NULL);
|
||||
DEBUGASSERT(sshc->ssh_agent == NULL);
|
||||
|
||||
Curl_safefree(sshc->rsa_pub);
|
||||
Curl_safefree(sshc->rsa);
|
||||
Curl_safefree(sshc->quote_path1);
|
||||
Curl_safefree(sshc->quote_path2);
|
||||
Curl_safefree(sshc->homedir);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -3426,6 +3436,7 @@ static CURLcode ssh_done(struct Curl_easy *data, CURLcode status)
|
||||
|
||||
Curl_safefree(sshp->path);
|
||||
Curl_dyn_free(&sshp->readdir);
|
||||
Curl_dyn_free(&sshp->readdir_link);
|
||||
|
||||
if(Curl_pgrsDone(data))
|
||||
return CURLE_ABORTED_BY_CALLBACK;
|
||||
|
||||
@ -212,6 +212,7 @@ struct ssh_conn {
|
||||
byte handle[WOLFSSH_MAX_HANDLE];
|
||||
curl_off_t offset;
|
||||
#endif /* USE_LIBSSH */
|
||||
BIT(initialised);
|
||||
};
|
||||
|
||||
#ifdef USE_LIBSSH
|
||||
|
||||
Loading…
Reference in New Issue
Block a user