#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 */
void Curl_dyn_free(struct dynbuf *s)
{
DEBUGASSERT(s);
+ DEBUGASSERT(s->init == DYNINIT);
Curl_safefree(s->bufr);
s->leng = s->allc = 0;
}
*/
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);
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;
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;
Curl_safefree(ftpc->prevpath);
Curl_safefree(ftpc->server_os);
Curl_pp_disconnect(pp);
- Curl_sec_end(conn);
return CURLE_OK;
}
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) {
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
/* 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);
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);
+ /* 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 the SASL module */
+ Curl_sasl_cleanup(conn, imapc->sasl.authused);
- /* Cleanup our connection based variables */
- Curl_safefree(imapc->mailbox);
- Curl_safefree(imapc->mailbox_uidvalidity);
+ /* Cleanup our connection based variables */
+ Curl_safefree(imapc->mailbox);
+ Curl_safefree(imapc->mailbox_uidvalidity);
+ memset(imapc, 0, sizeof(*imapc));
+ }
return CURLE_OK;
}
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;
mech->name);
return CURLE_FAILED_INIT;
}
- Curl_dyn_init(&conn->in_buffer.buf, CURL_MAX_INPUT_LENGTH);
}
infof(data, "Trying mechanism %s...", mech->name);
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);
/* 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;
}
/***********************************************************************
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;
}
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) \
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;
}
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;
}
size_t rtp_len;
rtp_parse_st state;
BIT(in_header);
+ BIT(initialised);
};
/****************************************************************************
#include "hsts.h"
#include "noproxy.h"
#include "cfilters.h"
+#include "curl_krb5.h"
#include "idn.h"
/* And now for the protocols */
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);
-
- /* 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;
+ 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;
#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);
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);
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;
}
/* 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;
}
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;
}
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
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);
sshc->actualcode = result ? result : CURLE_SSH;
break;
}
- Curl_dyn_init(&sshp->readdir, CURL_PATH_MAX * 2);
state(data, SSH_SFTP_READDIR);
break;
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;
}
{
int rc;
- 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(sshc->initialised) {
+ if(sshc->kh) {
+ libssh2_knownhost_free(sshc->kh);
+ sshc->kh = NULL;
}
- 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_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;
- if(sshc->ssh_session) {
- rc = libssh2_session_free(sshc->ssh_session);
- if(!block && (rc == LIBSSH2_ERROR_EAGAIN)) {
- return rc;
+ /* 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(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);
+ 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;
+ }
return 0;
}
Curl_safefree(sshp->path);
Curl_dyn_free(&sshp->readdir);
+ Curl_dyn_free(&sshp->readdir_link);
if(Curl_pgrsDone(data))
return CURLE_ABORTED_BY_CALLBACK;
byte handle[WOLFSSH_MAX_HANDLE];
curl_off_t offset;
#endif /* USE_LIBSSH */
+ BIT(initialised);
};
#ifdef USE_LIBSSH