mirror of
https://github.com/curl/curl.git
synced 2026-07-24 19:57:25 +03:00
smb: use easy handle/connection meta hash to keep structs
Keep easy/connection related protoocl structs in the meta hash instead of the unions at request and connectdata. Closes #17238
This commit is contained in:
parent
cd3be116b6
commit
777c5209df
4 changed files with 210 additions and 174 deletions
|
|
@ -106,7 +106,6 @@ struct SingleRequest {
|
|||
struct IMAP *imap;
|
||||
struct ldapreqinfo *ldap;
|
||||
struct RTSP *rtsp;
|
||||
struct smb_request *smb;
|
||||
struct SMTP *smtp;
|
||||
struct SSHPROTO *ssh;
|
||||
struct TELNET *telnet;
|
||||
|
|
|
|||
356
lib/smb.c
356
lib/smb.c
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include "smb.h"
|
||||
#include "urldata.h"
|
||||
#include "url.h"
|
||||
#include "sendf.h"
|
||||
#include "multiif.h"
|
||||
#include "cfilters.h"
|
||||
|
|
@ -45,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
|
||||
*/
|
||||
|
|
@ -245,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
|
||||
|
|
@ -268,7 +320,7 @@ 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 */
|
||||
|
|
@ -297,7 +349,7 @@ 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 */
|
||||
|
|
@ -341,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[] = {
|
||||
|
|
@ -380,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 */
|
||||
};
|
||||
/* 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]);
|
||||
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
|
||||
|
|
@ -415,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)
|
||||
|
|
@ -472,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;
|
||||
|
|
@ -520,19 +586,16 @@ 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;
|
||||
|
||||
memset(h, 0, sizeof(*h));
|
||||
|
|
@ -549,11 +612,9 @@ static void smb_format_message(struct Curl_easy *data, struct smb_header *h,
|
|||
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;
|
||||
|
||||
|
|
@ -571,10 +632,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;
|
||||
|
|
@ -595,39 +654,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;
|
||||
|
||||
const size_t byte_count = sizeof(lm) + sizeof(nt) +
|
||||
if(!smbc || !req)
|
||||
return CURLE_FAILED_INIT;
|
||||
|
||||
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,19 +728,20 @@ static CURLcode smb_send_setup(struct Curl_easy *data)
|
|||
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,13 +759,14 @@ static CURLcode smb_send_tree_connect(struct Curl_easy *data)
|
|||
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;
|
||||
|
||||
|
|
@ -721,34 +789,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;
|
||||
|
||||
|
|
@ -761,15 +832,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;
|
||||
|
||||
|
|
@ -787,16 +858,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 */
|
||||
|
||||
|
|
@ -819,7 +889,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;
|
||||
}
|
||||
|
|
@ -828,18 +898,22 @@ 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(Curl_conn_is_ssl(conn, FIRSTSOCKET)) {
|
||||
|
|
@ -852,17 +926,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;
|
||||
|
|
@ -897,7 +971,7 @@ static CURLcode smb_connection_state(struct Curl_easy *data, bool *done)
|
|||
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:
|
||||
|
|
@ -906,16 +980,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;
|
||||
}
|
||||
|
|
@ -945,9 +1019,9 @@ static void get_posix_time(time_t *out, curl_off_t timestamp)
|
|||
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;
|
||||
|
|
@ -955,6 +1029,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;
|
||||
|
|
@ -962,7 +1039,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;
|
||||
|
|
@ -972,7 +1049,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;
|
||||
|
|
@ -1082,31 +1159,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:
|
||||
|
|
@ -1128,19 +1205,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)
|
||||
{
|
||||
|
|
@ -1152,26 +1216,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;
|
||||
|
||||
|
|
|
|||
24
lib/smb.h
24
lib/smb.h
|
|
@ -25,30 +25,6 @@
|
|||
*
|
||||
***************************************************************************/
|
||||
|
||||
enum smb_conn_state {
|
||||
SMB_NOT_CONNECTED = 0,
|
||||
SMB_CONNECTING,
|
||||
SMB_NEGOTIATE,
|
||||
SMB_SETUP,
|
||||
SMB_CONNECTED
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \
|
||||
(SIZEOF_CURL_OFF_T > 4)
|
||||
|
||||
|
|
|
|||
|
|
@ -875,9 +875,6 @@ struct connectdata {
|
|||
#ifndef CURL_DISABLE_RTSP
|
||||
struct rtsp_conn rtspc;
|
||||
#endif
|
||||
#ifndef CURL_DISABLE_SMB
|
||||
struct smb_conn smbc;
|
||||
#endif
|
||||
#ifdef USE_LIBRTMP
|
||||
void *rtmp;
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue