26 #if !defined(CURL_DISABLE_SMB) && defined(USE_NTLM) && \ 27 (CURL_SIZEOF_CURL_OFF_T > 4) 29 #if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO) 31 #define BUILDING_CURL_SMB_C 35 #ifdef CURL_WINDOWS_APP 36 #define getpid GetCurrentProcessId 38 #define getpid _getpid 100 smb_setup_connection,
105 smb_connection_state,
120 #define MAX_PAYLOAD_SIZE 0x8000 121 #define MAX_MESSAGE_SIZE (MAX_PAYLOAD_SIZE + 0x1000) 122 #define CLIENTNAME "curl" 123 #define SERVICENAME "?????" 126 #define MSGCAT(str) \ 131 #define MSGCATNULL(str) \ 133 p += strlen(str) + 1; 136 #if (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) || \ 138 static unsigned short smb_swap16(
unsigned short x)
140 return (
unsigned short) ((x << 8) | ((x >> 8) & 0xff));
143 static unsigned int smb_swap32(
unsigned int x)
145 return (x << 24) | ((x << 8) & 0xff0000) | ((x >> 8) & 0xff00) |
150 static unsigned long long smb_swap64(
unsigned long long x)
152 return ((
unsigned long long) smb_swap32((
unsigned int) x) << 32) |
153 smb_swap32((
unsigned int) (x >> 32));
156 static unsigned __int64 smb_swap64(
unsigned __int64 x)
158 return ((
unsigned __int64) smb_swap32((
unsigned int) x) << 32) |
159 smb_swap32((
unsigned int) (x >> 32));
163 # define smb_swap16(x) (x) 164 # define smb_swap32(x) (x) 165 # define smb_swap64(x) (x) 182 enum smb_req_state
state;
193 #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) 195 static const char *
const names[] = {
204 if(smb->
state != newstate)
205 infof(conn->
data,
"SMB conn %p state change from %s to %s\n",
206 (
void *)smb, names[smb->
state], names[newstate]);
209 smb->
state = newstate;
212 static void request_state(
struct connectdata *conn,
213 enum smb_req_state newstate)
216 #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) 218 static const char *
const names[] = {
225 "SMB_TREE_DISCONNECT",
230 if(req->state != newstate)
231 infof(conn->
data,
"SMB request %p state change from %s to %s\n",
232 (
void *)req, names[req->state], names[newstate]);
235 req->state = newstate;
240 struct smb_request *req;
248 return smb_parse_url_path(conn);
263 memset(smbc, 0,
sizeof(*smbc));
273 slash = strchr(conn->
user,
'/');
275 slash = strchr(conn->
user,
'\\');
278 smbc->
user = slash + 1;
301 size_t len = MAX_MESSAGE_SIZE - smbc->
got;
311 smbc->
got += bytes_read;
314 if(smbc->
got <
sizeof(
unsigned int))
318 (buf +
sizeof(
unsigned short))) +
319 sizeof(
unsigned int);
320 if(smbc->
got < nbt_size)
323 msg_size =
sizeof(
struct smb_header);
324 if(nbt_size >= msg_size + 1) {
326 msg_size += 1 + ((
unsigned char) buf[msg_size]) *
sizeof(
unsigned short);
327 if(nbt_size >= msg_size +
sizeof(
unsigned short)) {
329 msg_size +=
sizeof(
unsigned short) +
331 if(nbt_size < msg_size)
341 static void smb_pop_message(
struct connectdata *conn)
348 static void smb_format_message(
struct connectdata *conn,
struct smb_header *h,
349 unsigned char cmd,
size_t len)
355 memset(h, 0,
sizeof(*h));
356 h->nbt_length = htons((
unsigned short) (
sizeof(*h) -
sizeof(
unsigned int) +
358 memcpy((
char *)h->magic,
"\xffSMB", 4);
360 h->flags = SMB_FLAGS_CANONICAL_PATHNAMES | SMB_FLAGS_CASELESS_PATHNAMES;
361 h->flags2 = smb_swap16(SMB_FLAGS2_IS_LONG_NAME | SMB_FLAGS2_KNOWS_LONG_NAME);
362 h->uid = smb_swap16(smbc->
uid);
363 h->tid = smb_swap16(req->tid);
365 h->pid_high = smb_swap16((
unsigned short)(pid >> 16));
366 h->pid = smb_swap16((
unsigned short) pid);
377 len, &bytes_written);
381 if(bytes_written != len) {
383 smbc->
sent = bytes_written;
403 len, &bytes_written);
407 if(bytes_written != len)
408 smbc->
sent += bytes_written;
416 const void *msg,
size_t msg_len)
423 return smb_send(conn,
sizeof(
struct smb_header) + msg_len, 0);
428 const char *msg =
"\x00\x0c\x00\x02NT LM 0.12";
430 return smb_send_message(conn, SMB_COM_NEGOTIATE, msg, 15);
436 struct smb_setup msg;
438 unsigned char lm_hash[21];
439 unsigned char lm[24];
440 unsigned char nt_hash[21];
441 unsigned char nt[24];
443 size_t byte_count =
sizeof(lm) +
sizeof(nt);
444 byte_count += strlen(smbc->
user) + strlen(smbc->
domain);
445 byte_count += strlen(
OS) + strlen(CLIENTNAME) + 4;
446 if(byte_count >
sizeof(msg.bytes))
449 Curl_ntlm_core_mk_lm_hash(conn->
data, conn->
passwd, lm_hash);
450 Curl_ntlm_core_lm_resp(lm_hash, smbc->
challenge, lm);
451 #ifdef USE_NTRESPONSES 452 Curl_ntlm_core_mk_nt_hash(conn->
data, conn->
passwd, nt_hash);
453 Curl_ntlm_core_lm_resp(nt_hash, smbc->
challenge, nt);
455 memset(nt, 0,
sizeof(nt));
458 memset(&msg, 0,
sizeof(msg));
459 msg.word_count = SMB_WC_SETUP_ANDX;
460 msg.andx.command = SMB_COM_NO_ANDX_COMMAND;
461 msg.max_buffer_size = smb_swap16(MAX_MESSAGE_SIZE);
462 msg.max_mpx_count = smb_swap16(1);
463 msg.vc_number = smb_swap16(1);
465 msg.capabilities = smb_swap32(SMB_CAP_LARGE_FILES);
466 msg.lengths[0] = smb_swap16(
sizeof(lm));
467 msg.lengths[1] = smb_swap16(
sizeof(nt));
468 memcpy(p, lm,
sizeof(lm));
470 memcpy(p, nt,
sizeof(nt));
472 MSGCATNULL(smbc->
user);
475 MSGCATNULL(CLIENTNAME);
476 byte_count = p - msg.bytes;
477 msg.byte_count = smb_swap16((
unsigned short)byte_count);
479 return smb_send_message(conn, SMB_COM_SETUP_ANDX, &msg,
480 sizeof(msg) -
sizeof(msg.bytes) + byte_count);
486 struct smb_tree_connect msg;
489 size_t byte_count = strlen(conn->
host.
name) + strlen(req->share);
490 byte_count += strlen(SERVICENAME) + 5;
491 if(byte_count >
sizeof(msg.bytes))
494 memset(&msg, 0,
sizeof(msg));
495 msg.word_count = SMB_WC_TREE_CONNECT_ANDX;
496 msg.andx.command = SMB_COM_NO_ANDX_COMMAND;
501 MSGCATNULL(req->share);
502 MSGCATNULL(SERVICENAME);
503 byte_count = p - msg.bytes;
504 msg.byte_count = smb_swap16((
unsigned short)byte_count);
506 return smb_send_message(conn, SMB_COM_TREE_CONNECT_ANDX, &msg,
507 sizeof(msg) -
sizeof(msg.bytes) + byte_count);
513 struct smb_nt_create msg;
516 if((strlen(req->path) + 1) >
sizeof(msg.bytes))
519 memset(&msg, 0,
sizeof(msg));
520 msg.word_count = SMB_WC_NT_CREATE_ANDX;
521 msg.andx.command = SMB_COM_NO_ANDX_COMMAND;
522 byte_count = strlen(req->path);
523 msg.name_length = smb_swap16((
unsigned short)byte_count);
524 msg.share_access = smb_swap32(SMB_FILE_SHARE_ALL);
526 msg.access = smb_swap32(SMB_GENERIC_READ | SMB_GENERIC_WRITE);
527 msg.create_disposition = smb_swap32(SMB_FILE_OVERWRITE_IF);
530 msg.access = smb_swap32(SMB_GENERIC_READ);
531 msg.create_disposition = smb_swap32(SMB_FILE_OPEN);
533 msg.byte_count = smb_swap16((
unsigned short) ++byte_count);
534 strcpy(msg.bytes, req->path);
536 return smb_send_message(conn, SMB_COM_NT_CREATE_ANDX, &msg,
537 sizeof(msg) -
sizeof(msg.bytes) + byte_count);
543 struct smb_close msg;
545 memset(&msg, 0,
sizeof(msg));
546 msg.word_count = SMB_WC_CLOSE;
547 msg.fid = smb_swap16(req->fid);
549 return smb_send_message(conn, SMB_COM_CLOSE, &msg,
sizeof(msg));
554 struct smb_tree_disconnect msg;
556 memset(&msg, 0,
sizeof(msg));
558 return smb_send_message(conn, SMB_COM_TREE_DISCONNECT, &msg,
sizeof(msg));
567 memset(&msg, 0,
sizeof(msg));
568 msg.word_count = SMB_WC_READ_ANDX;
569 msg.andx.command = SMB_COM_NO_ANDX_COMMAND;
570 msg.fid = smb_swap16(req->fid);
571 msg.offset = smb_swap32((
unsigned int) offset);
572 msg.offset_high = smb_swap32((
unsigned int) (offset >> 32));
573 msg.min_bytes = smb_swap16(MAX_PAYLOAD_SIZE);
574 msg.max_bytes = smb_swap16(MAX_PAYLOAD_SIZE);
576 return smb_send_message(conn, SMB_COM_READ_ANDX, &msg,
sizeof(msg));
586 if(upload_size >= MAX_PAYLOAD_SIZE - 1)
587 upload_size = MAX_PAYLOAD_SIZE - 1;
589 memset(msg, 0,
sizeof(*msg));
590 msg->word_count = SMB_WC_WRITE_ANDX;
591 msg->andx.command = SMB_COM_NO_ANDX_COMMAND;
592 msg->fid = smb_swap16(req->fid);
593 msg->offset = smb_swap32((
unsigned int) offset);
594 msg->offset_high = smb_swap32((
unsigned int) (offset >> 32));
595 msg->data_length = smb_swap16((
unsigned short) upload_size);
596 msg->data_offset = smb_swap16(
sizeof(*msg) -
sizeof(
unsigned int));
597 msg->byte_count = smb_swap16((
unsigned short) (upload_size + 1));
599 smb_format_message(conn, &msg->h, SMB_COM_WRITE_ANDX,
600 sizeof(*msg) -
sizeof(msg->h) + (
size_t) upload_size);
602 return smb_send(conn,
sizeof(*msg), (
size_t) upload_size);
628 result = smb_flush(conn);
637 return smb_recv_message(conn, msg);
643 struct smb_negotiate_response *nrsp;
644 struct smb_header *h;
660 result = smb_send_negotiate(conn);
662 connclose(conn,
"SMB: failed to send negotiate message");
670 result = smb_send_and_recv(conn, &msg);
672 connclose(conn,
"SMB: failed to communicate");
681 switch(smbc->
state) {
683 if(h->status || smbc->
got <
sizeof(*nrsp) +
sizeof(smbc->
challenge) - 1) {
684 connclose(conn,
"SMB: negotiation failed");
690 result = smb_send_setup(conn);
692 connclose(conn,
"SMB: failed to send setup message");
700 connclose(conn,
"SMB: authentication failed");
703 smbc->
uid = smb_swap16(h->uid);
709 smb_pop_message(conn);
713 smb_pop_message(conn);
722 static void get_posix_time(
long *_out,
const void *_in)
725 long long timestamp = *(
long long *) _in;
727 unsigned __int64 timestamp = *(
unsigned __int64 *) _in;
730 timestamp -= 116444736000000000ULL;
731 timestamp /= 10000000;
732 *_out = (long) timestamp;
738 struct smb_header *h;
740 enum smb_req_state next_state = SMB_DONE;
745 const struct smb_nt_create_response *smb_m;
748 if(req->state == SMB_REQUESTING) {
749 result = smb_send_tree_connect(conn);
751 connclose(conn,
"SMB: failed to send tree connect message");
755 request_state(conn, SMB_TREE_CONNECT);
759 result = smb_send_and_recv(conn, &msg);
761 connclose(conn,
"SMB: failed to communicate");
771 case SMB_TREE_CONNECT:
774 if(h->status == smb_swap32(SMB_ERR_NOACCESS))
778 req->tid = smb_swap16(h->tid);
779 next_state = SMB_OPEN;
783 if(h->status || smbc->
got <
sizeof(
struct smb_nt_create_response)) {
785 next_state = SMB_TREE_DISCONNECT;
788 smb_m = (
const struct smb_nt_create_response*) msg;
789 req->fid = smb_swap16(smb_m->fid);
794 next_state = SMB_UPLOAD;
797 smb_m = (
const struct smb_nt_create_response*) msg;
798 conn->
data->
req.
size = smb_swap64(smb_m->end_of_file);
802 next_state = SMB_DOWNLOAD;
807 if(h->status || smbc->
got <
sizeof(
struct smb_header) + 14) {
809 next_state = SMB_CLOSE;
813 sizeof(
struct smb_header) + 11);
815 sizeof(
struct smb_header) + 13);
817 if(off +
sizeof(
unsigned int) + len > smbc->
got) {
818 failf(conn->
data,
"Invalid input packet");
823 (
char *)msg + off +
sizeof(
unsigned int),
827 next_state = SMB_CLOSE;
834 next_state = (len < MAX_PAYLOAD_SIZE) ? SMB_CLOSE : SMB_DOWNLOAD;
838 if(h->status || smbc->
got <
sizeof(
struct smb_header) + 6) {
840 next_state = SMB_CLOSE;
844 sizeof(
struct smb_header) + 5);
849 next_state = SMB_CLOSE;
851 next_state = SMB_UPLOAD;
856 next_state = SMB_TREE_DISCONNECT;
859 case SMB_TREE_DISCONNECT:
860 next_state = SMB_DONE;
864 smb_pop_message(conn);
868 smb_pop_message(conn);
872 result = smb_send_open(conn);
876 result = smb_send_read(conn);
880 result = smb_send_write(conn);
884 result = smb_send_close(conn);
887 case SMB_TREE_DISCONNECT:
888 result = smb_send_tree_disconnect(conn);
892 result = req->result;
901 connclose(conn,
"SMB: failed to send message");
905 request_state(conn, next_state);
961 struct smb_request *req = data->
req.
protop;
971 req->share =
strdup((*path ==
'/' || *path ==
'\\') ? path + 1 : path);
978 slash = strchr(req->share,
'/');
980 slash = strchr(req->share,
'\\');
993 for(; *slash; slash++) {
CURLcode Curl_urldecode(struct Curl_easy *data, const char *string, size_t length, char **ostring, size_t *olen, bool reject_ctrl)
unsigned char challenge[8]
void Curl_pgrsSetUploadCounter(struct Curl_easy *data, curl_off_t size)
unsigned short Curl_read16_be(const unsigned char *buf)
const struct Curl_handler * handler
#define GETSOCK_READSOCK(x)
#define Curl_ssl_connect_nonblocking(x, y, z)
UNITTEST_START int result
memcpy(filename, filename1, strlen(filename1))
void Curl_pgrsSetUploadSize(struct Curl_easy *data, curl_off_t size)
void Curl_pgrsSetDownloadSize(struct Curl_easy *data, curl_off_t size)
CURL_TYPEOF_CURL_OFF_T curl_off_t
CURLcode Curl_write(struct connectdata *conn, curl_socket_t sockfd, const void *mem, size_t len, ssize_t *written)
CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp)
#define GETSOCK_WRITESOCK(x)
unsigned short Curl_read16_le(const unsigned char *buf)
CURLcode Curl_client_write(struct connectdata *conn, int type, char *ptr, size_t len)
#define Curl_safefree(ptr)
char uploadbuffer[UPLOAD_BUFSIZE+1]
void Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size)
union connectdata::@34 proto
enum smb_conn_state state
#define calloc(nbelem, size)
CURLcode Curl_read(struct connectdata *conn, curl_socket_t sockfd, char *buf, size_t sizerequested, ssize_t *n)