summaryrefslogtreecommitdiff
path: root/libs/libcurl/src/smb.c
diff options
context:
space:
mode:
Diffstat (limited to 'libs/libcurl/src/smb.c')
-rw-r--r--libs/libcurl/src/smb.c406
1 files changed, 239 insertions, 167 deletions
diff --git a/libs/libcurl/src/smb.c b/libs/libcurl/src/smb.c
index b99064820b..bf8394eb08 100644
--- a/libs/libcurl/src/smb.c
+++ b/libs/libcurl/src/smb.c
@@ -27,14 +27,9 @@
#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE)
-#ifdef _WIN32
-#define Curl_getpid() ((unsigned int)GetCurrentProcessId())
-#else
-#define Curl_getpid() ((unsigned int)getpid())
-#endif
-
#include "smb.h"
#include "urldata.h"
+#include "url.h"
#include "sendf.h"
#include "multiif.h"
#include "cfilters.h"
@@ -51,6 +46,58 @@
#include "curl_memory.h"
#include "memdebug.h"
+
+/* meta key for storing protocol meta at easy handle */
+#define CURL_META_SMB_EASY "meta:proto:smb:easy"
+/* meta key for storing protocol meta at connection */
+#define CURL_META_SMB_CONN "meta:proto:smb:conn"
+
+enum smb_conn_state {
+ SMB_NOT_CONNECTED = 0,
+ SMB_CONNECTING,
+ SMB_NEGOTIATE,
+ SMB_SETUP,
+ SMB_CONNECTED
+};
+
+/* SMB connection data, kept at connection */
+struct smb_conn {
+ enum smb_conn_state state;
+ char *user;
+ char *domain;
+ char *share;
+ unsigned char challenge[8];
+ unsigned int session_key;
+ unsigned short uid;
+ char *recv_buf;
+ char *send_buf;
+ size_t upload_size;
+ size_t send_size;
+ size_t sent;
+ size_t got;
+};
+
+/* SMB request state */
+enum smb_req_state {
+ SMB_REQUESTING,
+ SMB_TREE_CONNECT,
+ SMB_OPEN,
+ SMB_DOWNLOAD,
+ SMB_UPLOAD,
+ SMB_CLOSE,
+ SMB_TREE_DISCONNECT,
+ SMB_DONE
+};
+
+/* SMB request data, kept at easy handle */
+struct smb_request {
+ enum smb_req_state state;
+ char *path;
+ unsigned short tid; /* Even if we connect to the same tree as another */
+ unsigned short fid; /* request, the tid will be different */
+ CURLcode result;
+};
+
/*
* Definitions for SMB protocol data structures
*/
@@ -83,7 +130,7 @@
#define SMB_FLAGS_CANONICAL_PATHNAMES 0x10
#define SMB_FLAGS_CASELESS_PATHNAMES 0x08
-#define SMB_FLAGS2_UNICODE_STRINGS 0x8000
+/* #define SMB_FLAGS2_UNICODE_STRINGS 0x8000 */
#define SMB_FLAGS2_IS_LONG_NAME 0x0040
#define SMB_FLAGS2_KNOWS_LONG_NAME 0x0001
@@ -251,12 +298,11 @@ static CURLcode smb_connect(struct Curl_easy *data, bool *done);
static CURLcode smb_connection_state(struct Curl_easy *data, bool *done);
static CURLcode smb_do(struct Curl_easy *data, bool *done);
static CURLcode smb_request_state(struct Curl_easy *data, bool *done);
-static CURLcode smb_disconnect(struct Curl_easy *data,
- struct connectdata *conn, bool dead);
static int smb_getsock(struct Curl_easy *data, struct connectdata *conn,
curl_socket_t *socks);
static CURLcode smb_parse_url_path(struct Curl_easy *data,
- struct connectdata *conn);
+ struct smb_conn *smbc,
+ struct smb_request *req);
/*
* SMB handler interface
@@ -274,11 +320,12 @@ const struct Curl_handler Curl_handler_smb = {
smb_getsock, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
- smb_disconnect, /* disconnect */
+ ZERO_NULL, /* disconnect */
ZERO_NULL, /* write_resp */
ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
+ ZERO_NULL, /* follow */
PORT_SMB, /* defport */
CURLPROTO_SMB, /* protocol */
CURLPROTO_SMB, /* family */
@@ -302,11 +349,12 @@ const struct Curl_handler Curl_handler_smbs = {
smb_getsock, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
- smb_disconnect, /* disconnect */
+ ZERO_NULL, /* disconnect */
ZERO_NULL, /* write_resp */
ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
+ ZERO_NULL, /* follow */
PORT_SMBS, /* defport */
CURLPROTO_SMBS, /* protocol */
CURLPROTO_SMB, /* family */
@@ -345,30 +393,9 @@ static curl_off_t smb_swap64(curl_off_t x)
# define smb_swap64(x) (x)
#endif
-/* SMB request state */
-enum smb_req_state {
- SMB_REQUESTING,
- SMB_TREE_CONNECT,
- SMB_OPEN,
- SMB_DOWNLOAD,
- SMB_UPLOAD,
- SMB_CLOSE,
- SMB_TREE_DISCONNECT,
- SMB_DONE
-};
-
-/* SMB request data */
-struct smb_request {
- enum smb_req_state state;
- char *path;
- unsigned short tid; /* Even if we connect to the same tree as another */
- unsigned short fid; /* request, the tid will be different */
- CURLcode result;
-};
-
-static void conn_state(struct Curl_easy *data, enum smb_conn_state newstate)
+static void conn_state(struct Curl_easy *data, struct smb_conn *smbc,
+ enum smb_conn_state newstate)
{
- struct smb_conn *smbc = &data->conn->proto.smbc;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* For debug purposes */
static const char * const names[] = {
@@ -384,34 +411,59 @@ static void conn_state(struct Curl_easy *data, enum smb_conn_state newstate)
infof(data, "SMB conn %p state change from %s to %s",
(void *)smbc, names[smbc->state], names[newstate]);
#endif
-
+ (void)data;
smbc->state = newstate;
}
static void request_state(struct Curl_easy *data,
enum smb_req_state newstate)
{
- struct smb_request *req = data->req.p.smb;
+ struct smb_request *req = Curl_meta_get(data, CURL_META_SMB_EASY);
+ if(req) {
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
- /* For debug purposes */
- static const char * const names[] = {
- "SMB_REQUESTING",
- "SMB_TREE_CONNECT",
- "SMB_OPEN",
- "SMB_DOWNLOAD",
- "SMB_UPLOAD",
- "SMB_CLOSE",
- "SMB_TREE_DISCONNECT",
- "SMB_DONE",
- /* LAST */
- };
-
- if(req->state != newstate)
- infof(data, "SMB request %p state change from %s to %s",
- (void *)req, names[req->state], names[newstate]);
+ /* For debug purposes */
+ static const char * const names[] = {
+ "SMB_REQUESTING",
+ "SMB_TREE_CONNECT",
+ "SMB_OPEN",
+ "SMB_DOWNLOAD",
+ "SMB_UPLOAD",
+ "SMB_CLOSE",
+ "SMB_TREE_DISCONNECT",
+ "SMB_DONE",
+ /* LAST */
+ };
+
+ if(req->state != newstate)
+ infof(data, "SMB request %p state change from %s to %s",
+ (void *)req, names[req->state], names[newstate]);
#endif
- req->state = newstate;
+ req->state = newstate;
+ }
+}
+
+static void smb_easy_dtor(void *key, size_t klen, void *entry)
+{
+ struct smb_request *req = entry;
+ (void)key;
+ (void)klen;
+ /* `req->path` points to somewhere in `struct smb_conn` which is
+ * kept at the connection meta. If the connection is destroyed first,
+ * req->path points to free'd memory. */
+ free(req);
+}
+
+static void smb_conn_dtor(void *key, size_t klen, void *entry)
+{
+ struct smb_conn *smbc = entry;
+ (void)key;
+ (void)klen;
+ Curl_safefree(smbc->share);
+ Curl_safefree(smbc->domain);
+ Curl_safefree(smbc->recv_buf);
+ Curl_safefree(smbc->send_buf);
+ free(smbc);
}
/* this should setup things in the connection, not in the easy
@@ -419,24 +471,34 @@ static void request_state(struct Curl_easy *data,
static CURLcode smb_setup_connection(struct Curl_easy *data,
struct connectdata *conn)
{
+ struct smb_conn *smbc;
struct smb_request *req;
+ /* Initialize the connection state */
+ smbc = calloc(1, sizeof(*smbc));
+ if(!smbc ||
+ Curl_conn_meta_set(conn, CURL_META_SMB_CONN, smbc, smb_conn_dtor))
+ return CURLE_OUT_OF_MEMORY;
+
/* Initialize the request state */
- data->req.p.smb = req = calloc(1, sizeof(struct smb_request));
- if(!req)
+ req = calloc(1, sizeof(*req));
+ if(!req ||
+ Curl_meta_set(data, CURL_META_SMB_EASY, req, smb_easy_dtor))
return CURLE_OUT_OF_MEMORY;
/* Parse the URL path */
- return smb_parse_url_path(data, conn);
+ return smb_parse_url_path(data, smbc, req);
}
static CURLcode smb_connect(struct Curl_easy *data, bool *done)
{
struct connectdata *conn = data->conn;
- struct smb_conn *smbc = &conn->proto.smbc;
+ struct smb_conn *smbc = Curl_conn_meta_get(conn, CURL_META_SMB_CONN);
char *slash;
(void) done;
+ if(!smbc)
+ return CURLE_FAILED_INIT;
/* Check we have a username and password to authenticate with */
if(!data->state.aptr.user)
@@ -476,10 +538,10 @@ static CURLcode smb_connect(struct Curl_easy *data, bool *done)
return CURLE_OK;
}
-static CURLcode smb_recv_message(struct Curl_easy *data, void **msg)
+static CURLcode smb_recv_message(struct Curl_easy *data,
+ struct smb_conn *smbc,
+ void **msg)
{
- struct connectdata *conn = data->conn;
- struct smb_conn *smbc = &conn->proto.smbc;
char *buf = smbc->recv_buf;
ssize_t bytes_read;
size_t nbt_size;
@@ -524,20 +586,17 @@ static CURLcode smb_recv_message(struct Curl_easy *data, void **msg)
return CURLE_OK;
}
-static void smb_pop_message(struct connectdata *conn)
+static void smb_pop_message(struct smb_conn *smbc)
{
- struct smb_conn *smbc = &conn->proto.smbc;
-
smbc->got = 0;
}
-static void smb_format_message(struct Curl_easy *data, struct smb_header *h,
+static void smb_format_message(struct smb_conn *smbc,
+ struct smb_request *req,
+ struct smb_header *h,
unsigned char cmd, size_t len)
{
- struct connectdata *conn = data->conn;
- struct smb_conn *smbc = &conn->proto.smbc;
- struct smb_request *req = data->req.p.smb;
- unsigned int pid;
+ const unsigned int pid = 0xbad71d; /* made up */
memset(h, 0, sizeof(*h));
h->nbt_length = htons((unsigned short) (sizeof(*h) - sizeof(unsigned int) +
@@ -548,16 +607,13 @@ static void smb_format_message(struct Curl_easy *data, struct smb_header *h,
h->flags2 = smb_swap16(SMB_FLAGS2_IS_LONG_NAME | SMB_FLAGS2_KNOWS_LONG_NAME);
h->uid = smb_swap16(smbc->uid);
h->tid = smb_swap16(req->tid);
- pid = Curl_getpid();
h->pid_high = smb_swap16((unsigned short)(pid >> 16));
h->pid = smb_swap16((unsigned short) pid);
}
-static CURLcode smb_send(struct Curl_easy *data, size_t len,
- size_t upload_size)
+static CURLcode smb_send(struct Curl_easy *data, struct smb_conn *smbc,
+ size_t len, size_t upload_size)
{
- struct connectdata *conn = data->conn;
- struct smb_conn *smbc = &conn->proto.smbc;
size_t bytes_written;
CURLcode result;
@@ -575,10 +631,8 @@ static CURLcode smb_send(struct Curl_easy *data, size_t len,
return CURLE_OK;
}
-static CURLcode smb_flush(struct Curl_easy *data)
+static CURLcode smb_flush(struct Curl_easy *data, struct smb_conn *smbc)
{
- struct connectdata *conn = data->conn;
- struct smb_conn *smbc = &conn->proto.smbc;
size_t bytes_written;
size_t len = smbc->send_size - smbc->sent;
CURLcode result;
@@ -599,39 +653,46 @@ static CURLcode smb_flush(struct Curl_easy *data)
return CURLE_OK;
}
-static CURLcode smb_send_message(struct Curl_easy *data, unsigned char cmd,
+static CURLcode smb_send_message(struct Curl_easy *data,
+ struct smb_conn *smbc,
+ struct smb_request *req,
+ unsigned char cmd,
const void *msg, size_t msg_len)
{
- struct connectdata *conn = data->conn;
- struct smb_conn *smbc = &conn->proto.smbc;
-
- smb_format_message(data, (struct smb_header *)smbc->send_buf,
+ smb_format_message(smbc, req, (struct smb_header *)smbc->send_buf,
cmd, msg_len);
DEBUGASSERT((sizeof(struct smb_header) + msg_len) <= MAX_MESSAGE_SIZE);
memcpy(smbc->send_buf + sizeof(struct smb_header), msg, msg_len);
- return smb_send(data, sizeof(struct smb_header) + msg_len, 0);
+ return smb_send(data, smbc, sizeof(struct smb_header) + msg_len, 0);
}
-static CURLcode smb_send_negotiate(struct Curl_easy *data)
+static CURLcode smb_send_negotiate(struct Curl_easy *data,
+ struct smb_conn *smbc,
+ struct smb_request *req)
{
const char *msg = "\x00\x0c\x00\x02NT LM 0.12";
- return smb_send_message(data, SMB_COM_NEGOTIATE, msg, 15);
+ return smb_send_message(data, smbc, req, SMB_COM_NEGOTIATE, msg, 15);
}
static CURLcode smb_send_setup(struct Curl_easy *data)
{
struct connectdata *conn = data->conn;
- struct smb_conn *smbc = &conn->proto.smbc;
+ struct smb_conn *smbc = Curl_conn_meta_get(conn, CURL_META_SMB_CONN);
+ struct smb_request *req = Curl_meta_get(data, CURL_META_SMB_EASY);
struct smb_setup msg;
char *p = msg.bytes;
unsigned char lm_hash[21];
unsigned char lm[24];
unsigned char nt_hash[21];
unsigned char nt[24];
+ size_t byte_count;
+
+ if(!smbc || !req)
+ return CURLE_FAILED_INIT;
- const size_t byte_count = sizeof(lm) + sizeof(nt) +
+ byte_count = sizeof(lm) + sizeof(nt) +
strlen(smbc->user) + strlen(smbc->domain) +
strlen(CURL_OS) + strlen(CLIENTNAME) + 4; /* 4 null chars */
if(byte_count > sizeof(msg.bytes))
@@ -662,23 +723,24 @@ static CURLcode smb_send_setup(struct Curl_easy *data)
"%s%c" /* OS */
"%s", /* client name */
smbc->user, 0, smbc->domain, 0, CURL_OS, 0, CLIENTNAME);
- p++; /* count the final null termination */
+ p++; /* count the final null-termination */
DEBUGASSERT(byte_count == (size_t)(p - msg.bytes));
msg.byte_count = smb_swap16((unsigned short)byte_count);
- return smb_send_message(data, SMB_COM_SETUP_ANDX, &msg,
+ return smb_send_message(data, smbc, req, SMB_COM_SETUP_ANDX, &msg,
sizeof(msg) - sizeof(msg.bytes) + byte_count);
}
-static CURLcode smb_send_tree_connect(struct Curl_easy *data)
+static CURLcode smb_send_tree_connect(struct Curl_easy *data,
+ struct smb_conn *smbc,
+ struct smb_request *req)
{
struct smb_tree_connect msg;
struct connectdata *conn = data->conn;
- struct smb_conn *smbc = &conn->proto.smbc;
char *p = msg.bytes;
-
const size_t byte_count = strlen(conn->host.name) + strlen(smbc->share) +
strlen(SERVICENAME) + 5; /* 2 nulls and 3 backslashes */
+
if(byte_count > sizeof(msg.bytes))
return CURLE_FILESIZE_EXCEEDED;
@@ -692,17 +754,18 @@ static CURLcode smb_send_tree_connect(struct Curl_easy *data)
"%s%c" /* share */
"%s", /* service */
conn->host.name, smbc->share, 0, SERVICENAME);
- p++; /* count the final null termination */
+ p++; /* count the final null-termination */
DEBUGASSERT(byte_count == (size_t)(p - msg.bytes));
msg.byte_count = smb_swap16((unsigned short)byte_count);
- return smb_send_message(data, SMB_COM_TREE_CONNECT_ANDX, &msg,
+ return smb_send_message(data, smbc, req, SMB_COM_TREE_CONNECT_ANDX, &msg,
sizeof(msg) - sizeof(msg.bytes) + byte_count);
}
-static CURLcode smb_send_open(struct Curl_easy *data)
+static CURLcode smb_send_open(struct Curl_easy *data,
+ struct smb_conn *smbc,
+ struct smb_request *req)
{
- struct smb_request *req = data->req.p.smb;
struct smb_nt_create msg;
const size_t byte_count = strlen(req->path) + 1;
@@ -725,34 +788,37 @@ static CURLcode smb_send_open(struct Curl_easy *data)
msg.byte_count = smb_swap16((unsigned short) byte_count);
strcpy(msg.bytes, req->path);
- return smb_send_message(data, SMB_COM_NT_CREATE_ANDX, &msg,
+ return smb_send_message(data, smbc, req, SMB_COM_NT_CREATE_ANDX, &msg,
sizeof(msg) - sizeof(msg.bytes) + byte_count);
}
-static CURLcode smb_send_close(struct Curl_easy *data)
+static CURLcode smb_send_close(struct Curl_easy *data,
+ struct smb_conn *smbc,
+ struct smb_request *req)
{
- struct smb_request *req = data->req.p.smb;
struct smb_close msg;
memset(&msg, 0, sizeof(msg));
msg.word_count = SMB_WC_CLOSE;
msg.fid = smb_swap16(req->fid);
- return smb_send_message(data, SMB_COM_CLOSE, &msg, sizeof(msg));
+ return smb_send_message(data, smbc, req, SMB_COM_CLOSE, &msg, sizeof(msg));
}
-static CURLcode smb_send_tree_disconnect(struct Curl_easy *data)
+static CURLcode smb_send_tree_disconnect(struct Curl_easy *data,
+ struct smb_conn *smbc,
+ struct smb_request *req)
{
struct smb_tree_disconnect msg;
-
memset(&msg, 0, sizeof(msg));
-
- return smb_send_message(data, SMB_COM_TREE_DISCONNECT, &msg, sizeof(msg));
+ return smb_send_message(data, smbc, req, SMB_COM_TREE_DISCONNECT,
+ &msg, sizeof(msg));
}
-static CURLcode smb_send_read(struct Curl_easy *data)
+static CURLcode smb_send_read(struct Curl_easy *data,
+ struct smb_conn *smbc,
+ struct smb_request *req)
{
- struct smb_request *req = data->req.p.smb;
curl_off_t offset = data->req.offset;
struct smb_read msg;
@@ -765,15 +831,15 @@ static CURLcode smb_send_read(struct Curl_easy *data)
msg.min_bytes = smb_swap16(MAX_PAYLOAD_SIZE);
msg.max_bytes = smb_swap16(MAX_PAYLOAD_SIZE);
- return smb_send_message(data, SMB_COM_READ_ANDX, &msg, sizeof(msg));
+ return smb_send_message(data, smbc, req, SMB_COM_READ_ANDX,
+ &msg, sizeof(msg));
}
-static CURLcode smb_send_write(struct Curl_easy *data)
+static CURLcode smb_send_write(struct Curl_easy *data,
+ struct smb_conn *smbc,
+ struct smb_request *req)
{
- struct connectdata *conn = data->conn;
- struct smb_conn *smbc = &conn->proto.smbc;
struct smb_write *msg;
- struct smb_request *req = data->req.p.smb;
curl_off_t offset = data->req.offset;
curl_off_t upload_size = data->req.size - data->req.bytecount;
@@ -791,16 +857,15 @@ static CURLcode smb_send_write(struct Curl_easy *data)
msg->data_offset = smb_swap16(sizeof(*msg) - sizeof(unsigned int));
msg->byte_count = smb_swap16((unsigned short) (upload_size + 1));
- smb_format_message(data, &msg->h, SMB_COM_WRITE_ANDX,
+ smb_format_message(smbc, req, &msg->h, SMB_COM_WRITE_ANDX,
sizeof(*msg) - sizeof(msg->h) + (size_t) upload_size);
- return smb_send(data, sizeof(*msg), (size_t) upload_size);
+ return smb_send(data, smbc, sizeof(*msg), (size_t) upload_size);
}
-static CURLcode smb_send_and_recv(struct Curl_easy *data, void **msg)
+static CURLcode smb_send_and_recv(struct Curl_easy *data,
+ struct smb_conn *smbc, void **msg)
{
- struct connectdata *conn = data->conn;
- struct smb_conn *smbc = &conn->proto.smbc;
CURLcode result;
*msg = NULL; /* if it returns early */
@@ -823,7 +888,7 @@ static CURLcode smb_send_and_recv(struct Curl_easy *data, void **msg)
/* Check if there is data to send */
if(smbc->send_size) {
- result = smb_flush(data);
+ result = smb_flush(data, smbc);
if(result)
return result;
}
@@ -832,21 +897,25 @@ static CURLcode smb_send_and_recv(struct Curl_easy *data, void **msg)
if(smbc->send_size || smbc->upload_size)
return CURLE_AGAIN;
- return smb_recv_message(data, msg);
+ return smb_recv_message(data, smbc, msg);
}
static CURLcode smb_connection_state(struct Curl_easy *data, bool *done)
{
struct connectdata *conn = data->conn;
- struct smb_conn *smbc = &conn->proto.smbc;
+ struct smb_conn *smbc = Curl_conn_meta_get(conn, CURL_META_SMB_CONN);
+ struct smb_request *req = Curl_meta_get(data, CURL_META_SMB_EASY);
struct smb_negotiate_response *nrsp;
struct smb_header *h;
CURLcode result;
void *msg = NULL;
+ if(!smbc || !req)
+ return CURLE_FAILED_INIT;
+
if(smbc->state == SMB_CONNECTING) {
#ifdef USE_SSL
- if((conn->handler->flags & PROTOPT_SSL)) {
+ if(Curl_conn_is_ssl(conn, FIRSTSOCKET)) {
bool ssl_done = FALSE;
result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &ssl_done);
if(result && result != CURLE_AGAIN)
@@ -856,17 +925,17 @@ static CURLcode smb_connection_state(struct Curl_easy *data, bool *done)
}
#endif
- result = smb_send_negotiate(data);
+ result = smb_send_negotiate(data, smbc, req);
if(result) {
connclose(conn, "SMB: failed to send negotiate message");
return result;
}
- conn_state(data, SMB_NEGOTIATE);
+ conn_state(data, smbc, SMB_NEGOTIATE);
}
/* Send the previous message and check for a response */
- result = smb_send_and_recv(data, &msg);
+ result = smb_send_and_recv(data, smbc, &msg);
if(result && result != CURLE_AGAIN) {
connclose(conn, "SMB: failed to communicate");
return result;
@@ -885,14 +954,23 @@ static CURLcode smb_connection_state(struct Curl_easy *data, bool *done)
return CURLE_COULDNT_CONNECT;
}
nrsp = msg;
+#if defined(__GNUC__) && __GNUC__ >= 13
+#pragma GCC diagnostic push
+/* error: 'memcpy' offset [74, 80] from the object at '<unknown>' is out of
+ the bounds of referenced subobject 'bytes' with type 'char[1]' */
+#pragma GCC diagnostic ignored "-Warray-bounds"
+#endif
memcpy(smbc->challenge, nrsp->bytes, sizeof(smbc->challenge));
+#if defined(__GNUC__) && __GNUC__ >= 13
+#pragma GCC diagnostic pop
+#endif
smbc->session_key = smb_swap32(nrsp->session_key);
result = smb_send_setup(data);
if(result) {
connclose(conn, "SMB: failed to send setup message");
return result;
}
- conn_state(data, SMB_SETUP);
+ conn_state(data, smbc, SMB_SETUP);
break;
case SMB_SETUP:
@@ -901,16 +979,16 @@ static CURLcode smb_connection_state(struct Curl_easy *data, bool *done)
return CURLE_LOGIN_DENIED;
}
smbc->uid = smb_swap16(h->uid);
- conn_state(data, SMB_CONNECTED);
+ conn_state(data, smbc, SMB_CONNECTED);
*done = TRUE;
break;
default:
- smb_pop_message(conn);
+ smb_pop_message(smbc);
return CURLE_OK; /* ignore */
}
- smb_pop_message(conn);
+ smb_pop_message(smbc);
return CURLE_OK;
}
@@ -921,24 +999,28 @@ static CURLcode smb_connection_state(struct Curl_easy *data, bool *done)
*/
static void get_posix_time(time_t *out, curl_off_t timestamp)
{
- timestamp -= 116444736000000000;
- timestamp /= 10000000;
+ if(timestamp >= CURL_OFF_T_C(116444736000000000)) {
+ timestamp -= CURL_OFF_T_C(116444736000000000);
+ timestamp /= 10000000;
#if SIZEOF_TIME_T < SIZEOF_CURL_OFF_T
- if(timestamp > TIME_T_MAX)
- *out = TIME_T_MAX;
- else if(timestamp < TIME_T_MIN)
- *out = TIME_T_MIN;
- else
+ if(timestamp > TIME_T_MAX)
+ *out = TIME_T_MAX;
+ else if(timestamp < TIME_T_MIN)
+ *out = TIME_T_MIN;
+ else
#endif
- *out = (time_t) timestamp;
+ *out = (time_t) timestamp;
+ }
+ else
+ *out = 0;
}
static CURLcode smb_request_state(struct Curl_easy *data, bool *done)
{
struct connectdata *conn = data->conn;
- struct smb_request *req = data->req.p.smb;
+ struct smb_conn *smbc = Curl_conn_meta_get(conn, CURL_META_SMB_CONN);
+ struct smb_request *req = Curl_meta_get(data, CURL_META_SMB_EASY);
struct smb_header *h;
- struct smb_conn *smbc = &conn->proto.smbc;
enum smb_req_state next_state = SMB_DONE;
unsigned short len;
unsigned short off;
@@ -946,6 +1028,9 @@ static CURLcode smb_request_state(struct Curl_easy *data, bool *done)
void *msg = NULL;
const struct smb_nt_create_response *smb_m;
+ if(!smbc || !req)
+ return CURLE_FAILED_INIT;
+
if(data->state.upload && (data->state.infilesize < 0)) {
failf(data, "SMB upload needs to know the size up front");
return CURLE_SEND_ERROR;
@@ -953,7 +1038,7 @@ static CURLcode smb_request_state(struct Curl_easy *data, bool *done)
/* Start the request */
if(req->state == SMB_REQUESTING) {
- result = smb_send_tree_connect(data);
+ result = smb_send_tree_connect(data, smbc, req);
if(result) {
connclose(conn, "SMB: failed to send tree connect message");
return result;
@@ -963,7 +1048,7 @@ static CURLcode smb_request_state(struct Curl_easy *data, bool *done)
}
/* Send the previous message and check for a response */
- result = smb_send_and_recv(data, &msg);
+ result = smb_send_and_recv(data, smbc, &msg);
if(result && result != CURLE_AGAIN) {
connclose(conn, "SMB: failed to communicate");
return result;
@@ -1073,31 +1158,31 @@ static CURLcode smb_request_state(struct Curl_easy *data, bool *done)
break;
default:
- smb_pop_message(conn);
+ smb_pop_message(smbc);
return CURLE_OK; /* ignore */
}
- smb_pop_message(conn);
+ smb_pop_message(smbc);
switch(next_state) {
case SMB_OPEN:
- result = smb_send_open(data);
+ result = smb_send_open(data, smbc, req);
break;
case SMB_DOWNLOAD:
- result = smb_send_read(data);
+ result = smb_send_read(data, smbc, req);
break;
case SMB_UPLOAD:
- result = smb_send_write(data);
+ result = smb_send_write(data, smbc, req);
break;
case SMB_CLOSE:
- result = smb_send_close(data);
+ result = smb_send_close(data, smbc, req);
break;
case SMB_TREE_DISCONNECT:
- result = smb_send_tree_disconnect(data);
+ result = smb_send_tree_disconnect(data, smbc, req);
break;
case SMB_DONE:
@@ -1119,19 +1204,6 @@ static CURLcode smb_request_state(struct Curl_easy *data, bool *done)
return CURLE_OK;
}
-static CURLcode smb_disconnect(struct Curl_easy *data,
- struct connectdata *conn, bool dead)
-{
- struct smb_conn *smbc = &conn->proto.smbc;
- (void) dead;
- (void) data;
- Curl_safefree(smbc->share);
- Curl_safefree(smbc->domain);
- Curl_safefree(smbc->recv_buf);
- Curl_safefree(smbc->send_buf);
- return CURLE_OK;
-}
-
static int smb_getsock(struct Curl_easy *data,
struct connectdata *conn, curl_socket_t *socks)
{
@@ -1143,26 +1215,26 @@ static int smb_getsock(struct Curl_easy *data,
static CURLcode smb_do(struct Curl_easy *data, bool *done)
{
struct connectdata *conn = data->conn;
- struct smb_conn *smbc = &conn->proto.smbc;
+ struct smb_conn *smbc = Curl_conn_meta_get(conn, CURL_META_SMB_CONN);
*done = FALSE;
- if(smbc->share) {
+ if(!smbc)
+ return CURLE_FAILED_INIT;
+ if(smbc->share)
return CURLE_OK;
- }
return CURLE_URL_MALFORMAT;
}
static CURLcode smb_parse_url_path(struct Curl_easy *data,
- struct connectdata *conn)
+ struct smb_conn *smbc,
+ struct smb_request *req)
{
- struct smb_request *req = data->req.p.smb;
- struct smb_conn *smbc = &conn->proto.smbc;
char *path;
char *slash;
+ CURLcode result;
/* URL decode the path */
- CURLcode result = Curl_urldecode(data->state.up.path, 0, &path, NULL,
- REJECT_CTRL);
+ result = Curl_urldecode(data->state.up.path, 0, &path, NULL, REJECT_CTRL);
if(result)
return result;