summaryrefslogtreecommitdiff
path: root/source4/libcli
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2008-02-21 09:55:13 +1100
committerAndrew Bartlett <abartlet@samba.org>2008-02-21 09:55:13 +1100
commit774fa12ac1695600710ce9fac18024edd38161ee (patch)
tree5440d8c0f00d28656e0d8f65f3b771eb11a01842 /source4/libcli
parent49b3a4829325967df9d1e616ad32e5379ce6cf5d (diff)
parent910a1cafdf253255510d3aff7cc2385da43331dd (diff)
downloadsamba-774fa12ac1695600710ce9fac18024edd38161ee.tar.gz
samba-774fa12ac1695600710ce9fac18024edd38161ee.tar.bz2
samba-774fa12ac1695600710ce9fac18024edd38161ee.zip
Merge branch 'v4-0-test' of git://git.samba.org/samba into 4-0-local
(This used to be commit 5cd3310b78a85243eb436d05db3228c3495f9162)
Diffstat (limited to 'source4/libcli')
-rw-r--r--source4/libcli/composite/composite.c31
-rw-r--r--source4/libcli/config.mk10
-rw-r--r--source4/libcli/raw/clisession.c20
-rw-r--r--source4/libcli/raw/clitransport.c4
-rw-r--r--source4/libcli/raw/clitree.c6
-rw-r--r--source4/libcli/raw/interfaces.h68
-rw-r--r--source4/libcli/raw/libcliraw.h4
-rw-r--r--source4/libcli/raw/rawfile.c4
-rw-r--r--source4/libcli/raw/rawioctl.c2
-rw-r--r--source4/libcli/raw/rawnegotiate.c14
-rw-r--r--source4/libcli/raw/rawreadwrite.c9
-rw-r--r--source4/libcli/raw/rawrequest.c94
-rw-r--r--source4/libcli/raw/rawsearch.c2
-rw-r--r--source4/libcli/raw/rawsetfileinfo.c11
-rw-r--r--source4/libcli/raw/request.h19
-rw-r--r--source4/libcli/raw/smb_signing.c6
-rw-r--r--source4/libcli/smb2/cancel.c6
-rw-r--r--source4/libcli/smb2/connect.c10
-rw-r--r--source4/libcli/smb2/create.c52
-rw-r--r--source4/libcli/smb2/getinfo.c45
-rw-r--r--source4/libcli/smb2/logoff.c2
-rw-r--r--source4/libcli/smb2/negprot.c54
-rw-r--r--source4/libcli/smb2/notify.c2
-rw-r--r--source4/libcli/smb2/request.c101
-rw-r--r--source4/libcli/smb2/session.c24
-rw-r--r--source4/libcli/smb2/setinfo.c6
-rw-r--r--source4/libcli/smb2/smb2.h73
-rw-r--r--source4/libcli/smb2/smb2_calls.h61
-rw-r--r--source4/libcli/smb2/tcon.c18
-rw-r--r--source4/libcli/smb2/transport.c4
30 files changed, 518 insertions, 244 deletions
diff --git a/source4/libcli/composite/composite.c b/source4/libcli/composite/composite.c
index 67d5885497..aab7487a42 100644
--- a/source4/libcli/composite/composite.c
+++ b/source4/libcli/composite/composite.c
@@ -64,23 +64,6 @@ _PUBLIC_ NTSTATUS composite_wait(struct composite_context *c)
return c->status;
}
-
-/*
- * Some composite helpers that are handy if you write larger composite
- * functions.
- */
-_PUBLIC_ bool composite_is_ok(struct composite_context *ctx)
-{
- if (NT_STATUS_IS_OK(ctx->status)) {
- return true;
- }
- ctx->state = COMPOSITE_STATE_ERROR;
- if (ctx->async.fn != NULL) {
- ctx->async.fn(ctx);
- }
- return false;
-}
-
/*
callback from composite_done() and composite_error()
@@ -110,7 +93,10 @@ _PUBLIC_ void composite_error(struct composite_context *ctx, NTSTATUS status)
event_add_timed(ctx->event_ctx, ctx, timeval_zero(), composite_trigger, ctx);
}
ctx->status = status;
- SMB_ASSERT(!composite_is_ok(ctx));
+ ctx->state = COMPOSITE_STATE_ERROR;
+ if (ctx->async.fn != NULL) {
+ ctx->async.fn(ctx);
+ }
}
_PUBLIC_ bool composite_nomem(const void *p, struct composite_context *ctx)
@@ -122,6 +108,15 @@ _PUBLIC_ bool composite_nomem(const void *p, struct composite_context *ctx)
return true;
}
+_PUBLIC_ bool composite_is_ok(struct composite_context *ctx)
+{
+ if (NT_STATUS_IS_OK(ctx->status)) {
+ return true;
+ }
+ composite_error(ctx, ctx->status);
+ return false;
+}
+
_PUBLIC_ void composite_done(struct composite_context *ctx)
{
if (!ctx->used_wait && !ctx->async.fn) {
diff --git a/source4/libcli/config.mk b/source4/libcli/config.mk
index cf87e6c045..e4b6c71c8c 100644
--- a/source4/libcli/config.mk
+++ b/source4/libcli/config.mk
@@ -1,6 +1,6 @@
-include auth/config.mk
-include ldap/config.mk
-include security/config.mk
+mkinclude auth/config.mk
+mkinclude ldap/config.mk
+mkinclude security/config.mk
[SUBSYSTEM::LIBSAMBA-ERRORS]
PUBLIC_HEADERS = util/error.h util/ntstatus.h util/doserr.h util/werror.h
@@ -118,7 +118,7 @@ PUBLIC_DEPENDENCIES = LIBCLI_RAW LIBSAMBA-ERRORS LIBCLI_AUTH \
[SUBSYSTEM::LIBCLI_RAW]
PRIVATE_PROTO_HEADER = raw/raw_proto.h
PRIVATE_DEPENDENCIES = LIBCLI_COMPOSITE LP_RESOLVE gensec LIBCLI_RESOLVE LIBSECURITY LIBNDR
-LDFLAGS = $(SUBSYSTEM_LIBCLI_SMB_COMPOSITE_OUTPUT)
+#LDFLAGS = $(LIBCLI_SMB_COMPOSITE_OUTPUT)
PUBLIC_DEPENDENCIES = samba-socket LIBPACKET gensec LIBCRYPTO CREDENTIALS
OBJ_FILES = raw/rawfile.o \
raw/smb_signing.o \
@@ -144,4 +144,4 @@ OBJ_FILES = raw/rawfile.o \
raw/rawlpq.o \
raw/rawshadow.o
-include smb2/config.mk
+mkinclude smb2/config.mk
diff --git a/source4/libcli/raw/clisession.c b/source4/libcli/raw/clisession.c
index 617131c53c..55cb3ef305 100644
--- a/source4/libcli/raw/clisession.c
+++ b/source4/libcli/raw/clisession.c
@@ -177,9 +177,9 @@ NTSTATUS smb_raw_sesssetup_recv(struct smbcli_request *req,
parms->old.out.action = SVAL(req->in.vwv, VWV(2));
p = req->in.data;
if (p) {
- p += smbcli_req_pull_string(req, mem_ctx, &parms->old.out.os, p, -1, STR_TERMINATE);
- p += smbcli_req_pull_string(req, mem_ctx, &parms->old.out.lanman, p, -1, STR_TERMINATE);
- p += smbcli_req_pull_string(req, mem_ctx, &parms->old.out.domain, p, -1, STR_TERMINATE);
+ p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->old.out.os, p, -1, STR_TERMINATE);
+ p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->old.out.lanman, p, -1, STR_TERMINATE);
+ p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->old.out.domain, p, -1, STR_TERMINATE);
}
break;
@@ -190,10 +190,10 @@ NTSTATUS smb_raw_sesssetup_recv(struct smbcli_request *req,
parms->nt1.out.action = SVAL(req->in.vwv, VWV(2));
p = req->in.data;
if (p) {
- p += smbcli_req_pull_string(req, mem_ctx, &parms->nt1.out.os, p, -1, STR_TERMINATE);
- p += smbcli_req_pull_string(req, mem_ctx, &parms->nt1.out.lanman, p, -1, STR_TERMINATE);
+ p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->nt1.out.os, p, -1, STR_TERMINATE);
+ p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->nt1.out.lanman, p, -1, STR_TERMINATE);
if (p < (req->in.data + req->in.data_size)) {
- p += smbcli_req_pull_string(req, mem_ctx, &parms->nt1.out.domain, p, -1, STR_TERMINATE);
+ p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->nt1.out.domain, p, -1, STR_TERMINATE);
}
}
break;
@@ -209,11 +209,11 @@ NTSTATUS smb_raw_sesssetup_recv(struct smbcli_request *req,
break;
}
- parms->spnego.out.secblob = smbcli_req_pull_blob(req, mem_ctx, p, len);
+ parms->spnego.out.secblob = smbcli_req_pull_blob(&req->in.bufinfo, mem_ctx, p, len);
p += parms->spnego.out.secblob.length;
- p += smbcli_req_pull_string(req, mem_ctx, &parms->spnego.out.os, p, -1, STR_TERMINATE);
- p += smbcli_req_pull_string(req, mem_ctx, &parms->spnego.out.lanman, p, -1, STR_TERMINATE);
- p += smbcli_req_pull_string(req, mem_ctx, &parms->spnego.out.workgroup, p, -1, STR_TERMINATE);
+ p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->spnego.out.os, p, -1, STR_TERMINATE);
+ p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->spnego.out.lanman, p, -1, STR_TERMINATE);
+ p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->spnego.out.workgroup, p, -1, STR_TERMINATE);
break;
case RAW_SESSSETUP_SMB2:
diff --git a/source4/libcli/raw/clitransport.c b/source4/libcli/raw/clitransport.c
index 62c32d3058..288f0612de 100644
--- a/source4/libcli/raw/clitransport.c
+++ b/source4/libcli/raw/clitransport.c
@@ -444,6 +444,8 @@ static NTSTATUS smbcli_transport_finish_recv(void *private, DATA_BLOB blob)
req->in.ptr = req->in.data;
req->flags2 = SVAL(req->in.hdr, HDR_FLG2);
+ smb_setup_bufinfo(req);
+
if (!(req->flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
int class = CVAL(req->in.hdr,HDR_RCLS);
int code = SVAL(req->in.hdr,HDR_ERR);
@@ -637,7 +639,7 @@ NTSTATUS smb_raw_echo_recv(struct smbcli_request *req, TALLOC_CTX *mem_ctx,
p->out.data = talloc_array(mem_ctx, uint8_t, p->out.size);
NT_STATUS_HAVE_NO_MEMORY(p->out.data);
- if (!smbcli_raw_pull_data(req, req->in.data, p->out.size, p->out.data)) {
+ if (!smbcli_raw_pull_data(&req->in.bufinfo, req->in.data, p->out.size, p->out.data)) {
req->status = NT_STATUS_BUFFER_TOO_SMALL;
}
diff --git a/source4/libcli/raw/clitree.c b/source4/libcli/raw/clitree.c
index 35f3335322..507bde999a 100644
--- a/source4/libcli/raw/clitree.c
+++ b/source4/libcli/raw/clitree.c
@@ -123,9 +123,9 @@ NTSTATUS smb_raw_tcon_recv(struct smbcli_request *req, TALLOC_CTX *mem_ctx,
p = req->in.data;
if (!p) break;
- p += smbcli_req_pull_string(req, mem_ctx, &parms->tconx.out.dev_type,
- p, -1, STR_ASCII | STR_TERMINATE);
- p += smbcli_req_pull_string(req, mem_ctx, &parms->tconx.out.fs_type,
+ p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->tconx.out.dev_type,
+ p, -1, STR_ASCII | STR_TERMINATE);
+ p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->tconx.out.fs_type,
p, -1, STR_TERMINATE);
break;
diff --git a/source4/libcli/raw/interfaces.h b/source4/libcli/raw/interfaces.h
index 00ab788184..24e8ad4afc 100644
--- a/source4/libcli/raw/interfaces.h
+++ b/source4/libcli/raw/interfaces.h
@@ -260,20 +260,19 @@ union smb_tcon {
struct {
/* static body buffer 8 (0x08) bytes */
- /* uint16_t buffer_code; 0x09 = 0x08 + 1 */
- uint16_t unknown1; /* 0x0000 */
+ uint16_t reserved;
/* uint16_t path_ofs */
/* uint16_t path_size */
-
- /* dynamic body */
+ /* dynamic body */
const char *path; /* as non-terminated UTF-16 on the wire */
} in;
struct {
/* static body buffer 16 (0x10) bytes */
/* uint16_t buffer_code; 0x10 */
- uint16_t unknown1; /* 0x02 */
- uint32_t unknown2; /* 0x00 */
- uint32_t unknown3; /* 0x00 */
+ uint8_t share_type;
+ uint8_t reserved;
+ uint32_t flags;
+ uint32_t capabilities;
uint32_t access_mask;
/* extracted from the SMB2 header */
@@ -373,29 +372,22 @@ union smb_sesssetup {
enum smb_sesssetup_level level;
struct {
- /* NOTE: this was 0x11 = 0x10 + 1 in vista-CTP
- * and changed in vista-beta2, but both server's
- * can handle the 0x18 clients
- */
- /* static body buffer 24 (0x18) bytes */
- /* uint16_t buffer_code; 0x19 = 0x18 + 1 */
- uint16_t _pad;
- uint32_t unknown2; /* 0x0000000F(vista-CTP) 0x00000007(vista-beta2) */
- uint32_t unknown3; /* 0x0000000 */
+ /* static body 24 (0x18) bytes */
+ uint8_t vc_number;
+ uint8_t security_mode;
+ uint32_t capabilities;
+ uint32_t channel;
/* uint16_t secblob_ofs */
/* uint16_t secblob_size */
- uint64_t unknown4; /* 0x0000000000000000 only present in vista-beta2 */
-
+ uint64_t previous_sessionid;
/* dynamic body */
DATA_BLOB secblob;
} in;
struct {
- /* static body buffer 8 (0x08) bytes */
- /* uint16_t buffer_code; 0x09 = 0x08 +1 */
- uint16_t _pad;
+ /* body buffer 8 (0x08) bytes */
+ uint16_t session_flags;
/* uint16_t secblob_ofs */
/* uint16_t secblob_size */
-
/* dynamic body */
DATA_BLOB secblob;
@@ -910,7 +902,10 @@ enum smb_setfileinfo_level {
RAW_SFILEINFO_1029 = SMB_SFILEINFO_1029,
RAW_SFILEINFO_1032 = SMB_SFILEINFO_1032,
RAW_SFILEINFO_1039 = SMB_SFILEINFO_1039,
- RAW_SFILEINFO_1040 = SMB_SFILEINFO_1040
+ RAW_SFILEINFO_1040 = SMB_SFILEINFO_1040,
+
+ /* cope with breakage in SMB2 */
+ RAW_SFILEINFO_RENAME_INFORMATION_SMB2 = SMB_SFILEINFO_RENAME_INFORMATION|0x80000000,
};
/* union used in setfileinfo() and setpathinfo() calls */
@@ -1008,7 +1003,7 @@ union smb_setfileinfo {
struct {
union smb_handle_or_path file;
uint8_t overwrite;
- uint32_t root_fid;
+ uint64_t root_fid;
const char *new_name;
} in;
} rename_information;
@@ -1560,16 +1555,16 @@ union smb_open {
enum smb_open_level level;
struct {
/* static body buffer 56 (0x38) bytes */
- /* uint16_t buffer_code; 0x39 = 0x38 + 1 */
- uint16_t oplock_flags; /* SMB2_CREATE_FLAG_* */
- uint32_t impersonation;
- uint32_t unknown3[4];
- uint32_t access_mask;
-
- uint32_t file_attr;
- uint32_t share_access;
- uint32_t open_disposition;
- uint32_t create_options;
+ uint8_t security_flags; /* SMB2_SECURITY_* */
+ uint8_t oplock_level; /* SMB2_OPLOCK_LEVEL_* */
+ uint32_t impersonation_level; /* SMB2_IMPERSONATION_* */
+ uint64_t create_flags;
+ uint64_t reserved;
+ uint32_t desired_access;
+ uint32_t file_attributes;
+ uint32_t share_access; /* NTCREATEX_SHARE_ACCESS_* */
+ uint32_t create_disposition; /* NTCREATEX_DISP_* */
+ uint32_t create_options; /* NTCREATEX_OPTIONS_* */
/* uint16_t fname_ofs */
/* uint16_t fname_size */
@@ -1587,7 +1582,8 @@ union smb_open {
/* static body buffer 88 (0x58) bytes */
/* uint16_t buffer_code; 0x59 = 0x58 + 1 */
- uint16_t oplock_flags; /* SMB2_CREATE_FLAG_* */
+ uint8_t oplock_level;
+ uint8_t reserved;
uint32_t create_action;
NTTIME create_time;
NTTIME access_time;
@@ -1596,7 +1592,7 @@ union smb_open {
uint64_t alloc_size;
uint64_t size;
uint32_t file_attr;
- uint32_t _pad;
+ uint32_t reserved2;
/* struct smb2_handle handle;*/
/* uint32_t blob_ofs; */
/* uint32_t blob_size; */
diff --git a/source4/libcli/raw/libcliraw.h b/source4/libcli/raw/libcliraw.h
index 0032eb4e94..7111649fc1 100644
--- a/source4/libcli/raw/libcliraw.h
+++ b/source4/libcli/raw/libcliraw.h
@@ -250,8 +250,8 @@ struct smbcli_request {
/* the mid of this packet - used to match replies */
uint16_t mid;
- struct request_buffer in;
- struct request_buffer out;
+ struct smb_request_buffer in;
+ struct smb_request_buffer out;
/* information on what to do with a reply when it is received
asyncronously. If this is not setup when a reply is received then
diff --git a/source4/libcli/raw/rawfile.c b/source4/libcli/raw/rawfile.c
index 3b6ca68526..d9383401b7 100644
--- a/source4/libcli/raw/rawfile.c
+++ b/source4/libcli/raw/rawfile.c
@@ -616,7 +616,7 @@ NTSTATUS smb_raw_open_recv(struct smbcli_request *req, TALLOC_CTX *mem_ctx, unio
case RAW_OPEN_CTEMP:
SMBCLI_CHECK_WCT(req, 1);
parms->ctemp.out.file.fnum = SVAL(req->in.vwv, VWV(0));
- smbcli_req_pull_string(req, mem_ctx, &parms->ctemp.out.name, req->in.data, -1, STR_TERMINATE | STR_ASCII);
+ smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->ctemp.out.name, req->in.data, -1, STR_TERMINATE | STR_ASCII);
break;
case RAW_OPEN_SPLOPEN:
@@ -675,7 +675,7 @@ NTSTATUS smb_raw_open_recv(struct smbcli_request *req, TALLOC_CTX *mem_ctx, unio
parms->openxreadx.out.nread = SVAL(req->in.vwv, VWV(5));
if (parms->openxreadx.out.nread >
MAX(parms->openxreadx.in.mincnt, parms->openxreadx.in.maxcnt) ||
- !smbcli_raw_pull_data(req, req->in.hdr + SVAL(req->in.vwv, VWV(6)),
+ !smbcli_raw_pull_data(&req->in.bufinfo, req->in.hdr + SVAL(req->in.vwv, VWV(6)),
parms->openxreadx.out.nread,
parms->openxreadx.out.data)) {
req->status = NT_STATUS_BUFFER_TOO_SMALL;
diff --git a/source4/libcli/raw/rawioctl.c b/source4/libcli/raw/rawioctl.c
index 9205f84e86..957e554c6b 100644
--- a/source4/libcli/raw/rawioctl.c
+++ b/source4/libcli/raw/rawioctl.c
@@ -59,7 +59,7 @@ static NTSTATUS smb_raw_smbioctl_recv(struct smbcli_request *req,
return smbcli_request_destroy(req);
}
- parms->ioctl.out.blob = smbcli_req_pull_blob(req, mem_ctx, req->in.data, -1);
+ parms->ioctl.out.blob = smbcli_req_pull_blob(&req->in.bufinfo, mem_ctx, req->in.data, -1);
return smbcli_request_destroy(req);
}
diff --git a/source4/libcli/raw/rawnegotiate.c b/source4/libcli/raw/rawnegotiate.c
index fc7725cc55..ec2ada53ff 100644
--- a/source4/libcli/raw/rawnegotiate.c
+++ b/source4/libcli/raw/rawnegotiate.c
@@ -40,6 +40,10 @@ static const struct {
{PROTOCOL_LANMAN2,"Samba"},
{PROTOCOL_NT1,"NT LANMAN 1.0"},
{PROTOCOL_NT1,"NT LM 0.12"},
+#if 0
+ /* we don't yet handle chaining a SMB transport onto SMB2 */
+ {PROTOCOL_SMB2,"SMB 2.002"},
+#endif
};
/*
@@ -131,14 +135,14 @@ NTSTATUS smb_raw_negotiate_recv(struct smbcli_request *req)
if (req->in.data_size < 16) {
goto failed;
}
- transport->negotiate.server_guid = smbcli_req_pull_blob(req, transport, req->in.data, 16);
- transport->negotiate.secblob = smbcli_req_pull_blob(req, transport, req->in.data + 16, req->in.data_size - 16);
+ transport->negotiate.server_guid = smbcli_req_pull_blob(&req->in.bufinfo, transport, req->in.data, 16);
+ transport->negotiate.secblob = smbcli_req_pull_blob(&req->in.bufinfo, transport, req->in.data + 16, req->in.data_size - 16);
} else {
if (req->in.data_size < (transport->negotiate.key_len)) {
goto failed;
}
- transport->negotiate.secblob = smbcli_req_pull_blob(req, transport, req->in.data, transport->negotiate.key_len);
- smbcli_req_pull_string(req, transport, &transport->negotiate.server_domain,
+ transport->negotiate.secblob = smbcli_req_pull_blob(&req->in.bufinfo, transport, req->in.data, transport->negotiate.key_len);
+ smbcli_req_pull_string(&req->in.bufinfo, transport, &transport->negotiate.server_domain,
req->in.data+transport->negotiate.key_len,
req->in.data_size-transport->negotiate.key_len, STR_UNICODE|STR_NOALIGN);
/* here comes the server name */
@@ -164,7 +168,7 @@ NTSTATUS smb_raw_negotiate_recv(struct smbcli_request *req)
if ((SVAL(req->in.vwv,VWV(5)) & 0x2)) {
transport->negotiate.writebraw_supported = 1;
}
- transport->negotiate.secblob = smbcli_req_pull_blob(req, transport,
+ transport->negotiate.secblob = smbcli_req_pull_blob(&req->in.bufinfo, transport,
req->in.data, req->in.data_size);
} else {
/* the old core protocol */
diff --git a/source4/libcli/raw/rawreadwrite.c b/source4/libcli/raw/rawreadwrite.c
index b0c49ddab7..9e4edaf99c 100644
--- a/source4/libcli/raw/rawreadwrite.c
+++ b/source4/libcli/raw/rawreadwrite.c
@@ -137,7 +137,7 @@ NTSTATUS smb_raw_read_recv(struct smbcli_request *req, union smb_read *parms)
SMBCLI_CHECK_WCT(req, 5);
parms->lockread.out.nread = SVAL(req->in.vwv, VWV(0));
if (parms->lockread.out.nread > parms->lockread.in.count ||
- !smbcli_raw_pull_data(req, req->in.data+3,
+ !smbcli_raw_pull_data(&req->in.bufinfo, req->in.data+3,
parms->lockread.out.nread, parms->lockread.out.data)) {
req->status = NT_STATUS_BUFFER_TOO_SMALL;
}
@@ -148,7 +148,7 @@ NTSTATUS smb_raw_read_recv(struct smbcli_request *req, union smb_read *parms)
SMBCLI_CHECK_WCT(req, 5);
parms->read.out.nread = SVAL(req->in.vwv, VWV(0));
if (parms->read.out.nread > parms->read.in.count ||
- !smbcli_raw_pull_data(req, req->in.data+3,
+ !smbcli_raw_pull_data(&req->in.bufinfo, req->in.data+3,
parms->read.out.nread, parms->read.out.data)) {
req->status = NT_STATUS_BUFFER_TOO_SMALL;
}
@@ -171,11 +171,14 @@ NTSTATUS smb_raw_read_recv(struct smbcli_request *req, union smb_read *parms)
parms->readx.out.nread <=
req->in.buffer + req->in.size) {
req->in.data_size += (SVAL(req->in.vwv, VWV(7)) << 16);
+
+ /* update the bufinfo with the new size */
+ smb_setup_bufinfo(req);
}
}
if (parms->readx.out.nread > MAX(parms->readx.in.mincnt, parms->readx.in.maxcnt) ||
- !smbcli_raw_pull_data(req, req->in.hdr + SVAL(req->in.vwv, VWV(6)),
+ !smbcli_raw_pull_data(&req->in.bufinfo, req->in.hdr + SVAL(req->in.vwv, VWV(6)),
parms->readx.out.nread,
parms->readx.out.data)) {
req->status = NT_STATUS_BUFFER_TOO_SMALL;
diff --git a/source4/libcli/raw/rawrequest.c b/source4/libcli/raw/rawrequest.c
index e7dffaf054..355d092583 100644
--- a/source4/libcli/raw/rawrequest.c
+++ b/source4/libcli/raw/rawrequest.c
@@ -34,6 +34,20 @@
/* assume that a character will not consume more than 3 bytes per char */
#define MAX_BYTES_PER_CHAR 3
+/* setup the bufinfo used for strings and range checking */
+void smb_setup_bufinfo(struct smbcli_request *req)
+{
+ req->in.bufinfo.mem_ctx = req;
+ req->in.bufinfo.flags = 0;
+ if (req->flags2 & FLAGS2_UNICODE_STRINGS) {
+ req->in.bufinfo.flags = BUFINFO_FLAG_UNICODE;
+ }
+ req->in.bufinfo.align_base = req->in.buffer;
+ req->in.bufinfo.data = req->in.data;
+ req->in.bufinfo.data_size = req->in.data_size;
+}
+
+
/* destroy a request structure and return final status */
NTSTATUS smbcli_request_destroy(struct smbcli_request *req)
{
@@ -298,6 +312,9 @@ NTSTATUS smbcli_chained_advance(struct smbcli_request *req)
req->in.data = req->in.vwv + 2 + req->in.wct * 2;
req->in.data_size = SVAL(req->in.vwv, VWV(req->in.wct));
+ /* fix the bufinfo */
+ smb_setup_bufinfo(req);
+
if (buffer + 3 + req->in.wct*2 + req->in.data_size >
req->in.buffer + req->in.size) {
return NT_STATUS_BUFFER_TOO_SMALL;
@@ -544,13 +561,13 @@ size_t smbcli_req_append_var_block(struct smbcli_request *req, const uint8_t *by
on failure zero is returned and *dest is set to NULL, otherwise the number
of bytes consumed in the packet is returned
*/
-static size_t smbcli_req_pull_ucs2(struct smbcli_request *req, TALLOC_CTX *mem_ctx,
+static size_t smbcli_req_pull_ucs2(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx,
char **dest, const uint8_t *src, int byte_len, uint_t flags)
{
int src_len, src_len2, alignment=0;
ssize_t ret;
- if (!(flags & STR_NOALIGN) && ucs2_align(req->in.buffer, src, flags)) {
+ if (!(flags & STR_NOALIGN) && ucs2_align(bufinfo->align_base, src, flags)) {
src++;
alignment=1;
if (byte_len != -1) {
@@ -558,7 +575,7 @@ static size_t smbcli_req_pull_ucs2(struct smbcli_request *req, TALLOC_CTX *mem_c
}
}
- src_len = req->in.data_size - PTR_DIFF(src, req->in.data);
+ src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data);
if (src_len < 0) {
*dest = NULL;
return 0;
@@ -597,13 +614,13 @@ static size_t smbcli_req_pull_ucs2(struct smbcli_request *req, TALLOC_CTX *mem_c
on failure zero is returned and *dest is set to NULL, otherwise the number
of bytes consumed in the packet is returned
*/
-size_t smbcli_req_pull_ascii(struct smbcli_request *req, TALLOC_CTX *mem_ctx,
+size_t smbcli_req_pull_ascii(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx,
char **dest, const uint8_t *src, int byte_len, uint_t flags)
{
int src_len, src_len2;
ssize_t ret;
- src_len = req->in.data_size - PTR_DIFF(src, req->in.data);
+ src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data);
if (src_len < 0) {
*dest = NULL;
return 0;
@@ -640,15 +657,15 @@ size_t smbcli_req_pull_ascii(struct smbcli_request *req, TALLOC_CTX *mem_ctx,
on failure zero is returned and *dest is set to NULL, otherwise the number
of bytes consumed in the packet is returned
*/
-size_t smbcli_req_pull_string(struct smbcli_request *req, TALLOC_CTX *mem_ctx,
+size_t smbcli_req_pull_string(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx,
char **dest, const uint8_t *src, int byte_len, uint_t flags)
{
if (!(flags & STR_ASCII) &&
- (((flags & STR_UNICODE) || (req->flags2 & FLAGS2_UNICODE_STRINGS)))) {
- return smbcli_req_pull_ucs2(req, mem_ctx, dest, src, byte_len, flags);
+ (((flags & STR_UNICODE) || (bufinfo->flags & BUFINFO_FLAG_UNICODE)))) {
+ return smbcli_req_pull_ucs2(bufinfo, mem_ctx, dest, src, byte_len, flags);
}
- return smbcli_req_pull_ascii(req, mem_ctx, dest, src, byte_len, flags);
+ return smbcli_req_pull_ascii(bufinfo, mem_ctx, dest, src, byte_len, flags);
}
@@ -658,11 +675,11 @@ size_t smbcli_req_pull_string(struct smbcli_request *req, TALLOC_CTX *mem_ctx,
if byte_len is -1 then limit the blob only by packet size
*/
-DATA_BLOB smbcli_req_pull_blob(struct smbcli_request *req, TALLOC_CTX *mem_ctx, const uint8_t *src, int byte_len)
+DATA_BLOB smbcli_req_pull_blob(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx, const uint8_t *src, int byte_len)
{
int src_len;
- src_len = req->in.data_size - PTR_DIFF(src, req->in.data);
+ src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data);
if (src_len < 0) {
return data_blob(NULL, 0);
@@ -677,13 +694,13 @@ DATA_BLOB smbcli_req_pull_blob(struct smbcli_request *req, TALLOC_CTX *mem_ctx,
/* check that a lump of data in a request is within the bounds of the data section of
the packet */
-static bool smbcli_req_data_oob(struct smbcli_request *req, const uint8_t *ptr, uint32_t count)
+static bool smbcli_req_data_oob(struct request_bufinfo *bufinfo, const uint8_t *ptr, uint32_t count)
{
/* be careful with wraparound! */
- if (ptr < req->in.data ||
- ptr >= req->in.data + req->in.data_size ||
- count > req->in.data_size ||
- ptr + count > req->in.data + req->in.data_size) {
+ if (ptr < bufinfo->data ||
+ ptr >= bufinfo->data + bufinfo->data_size ||
+ count > bufinfo->data_size ||
+ ptr + count > bufinfo->data + bufinfo->data_size) {
return true;
}
return false;
@@ -694,11 +711,11 @@ static bool smbcli_req_data_oob(struct smbcli_request *req, const uint8_t *ptr,
return false if any part is outside the data portion of the packet
*/
-bool smbcli_raw_pull_data(struct smbcli_request *req, const uint8_t *src, int len, uint8_t *dest)
+bool smbcli_raw_pull_data(struct request_bufinfo *bufinfo, const uint8_t *src, int len, uint8_t *dest)
{
if (len == 0) return true;
- if (smbcli_req_data_oob(req, src, len)) {
+ if (smbcli_req_data_oob(bufinfo, src, len)) {
return false;
}
@@ -972,3 +989,44 @@ size_t smbcli_blob_append_string(struct smbcli_session *session,
return len;
}
+
+/*
+ pull a GUID structure from the wire. The buffer must be at least 16
+ bytes long
+ */
+enum ndr_err_code smbcli_pull_guid(void *base, uint16_t offset,
+ struct GUID *guid)
+{
+ DATA_BLOB blob;
+ TALLOC_CTX *tmp_ctx = talloc_new(NULL);
+ enum ndr_err_code ndr_err;
+
+ ZERO_STRUCTP(guid);
+
+ blob.data = offset + (uint8_t *)base;
+ blob.length = 16;
+ ndr_err = ndr_pull_struct_blob(&blob, tmp_ctx, NULL, guid,
+ (ndr_pull_flags_fn_t)ndr_pull_GUID);
+ talloc_free(tmp_ctx);
+ return ndr_err;
+}
+
+/*
+ push a guid onto the wire. The buffer must hold 16 bytes
+ */
+enum ndr_err_code smbcli_push_guid(void *base, uint16_t offset,
+ const struct GUID *guid)
+{
+ TALLOC_CTX *tmp_ctx = talloc_new(NULL);
+ enum ndr_err_code ndr_err;
+ DATA_BLOB blob;
+ ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, NULL,
+ guid, (ndr_push_flags_fn_t)ndr_push_GUID);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err) || blob.length != 16) {
+ talloc_free(tmp_ctx);
+ return ndr_err;
+ }
+ memcpy(offset + (uint8_t *)base, blob.data, blob.length);
+ talloc_free(tmp_ctx);
+ return ndr_err;
+}
diff --git a/source4/libcli/raw/rawsearch.c b/source4/libcli/raw/rawsearch.c
index 33fa90d68d..fb2b09467c 100644
--- a/source4/libcli/raw/rawsearch.c
+++ b/source4/libcli/raw/rawsearch.c
@@ -54,7 +54,7 @@ static void smb_raw_search_backend(struct smbcli_request *req,
search_data.search.write_time = raw_pull_dos_date(req->transport,
p + 22);
search_data.search.size = IVAL(p, 26);
- smbcli_req_pull_ascii(req, mem_ctx, &name, p+30, 13, STR_ASCII);
+ smbcli_req_pull_ascii(&req->in.bufinfo, mem_ctx, &name, p+30, 13, STR_ASCII);
search_data.search.name = name;
if (!callback(private, &search_data)) {
break;
diff --git a/source4/libcli/raw/rawsetfileinfo.c b/source4/libcli/raw/rawsetfileinfo.c
index a9a1a3547e..f1e4ee3686 100644
--- a/source4/libcli/raw/rawsetfileinfo.c
+++ b/source4/libcli/raw/rawsetfileinfo.c
@@ -75,6 +75,16 @@ bool smb_raw_setfileinfo_passthru(TALLOC_CTX *mem_ctx,
SIVAL(blob->data, 8, len - 2);
return true;
+ case RAW_SFILEINFO_RENAME_INFORMATION_SMB2:
+ NEED_BLOB(20);
+ SIVAL(blob->data, 0, parms->rename_information.in.overwrite);
+ SBVAL(blob->data, 8, parms->rename_information.in.root_fid);
+ len = smbcli_blob_append_string(NULL, mem_ctx, blob,
+ parms->rename_information.in.new_name,
+ STR_UNICODE|STR_TERMINATE);
+ SIVAL(blob->data, 16, len - 2);
+ return true;
+
case RAW_SFILEINFO_POSITION_INFORMATION:
NEED_BLOB(8);
SBVAL(blob->data, 0, parms->position_information.in.position);
@@ -229,6 +239,7 @@ static bool smb_raw_setinfo_backend(struct smbcli_tree *tree,
case RAW_SFILEINFO_UNIX_LINK:
case RAW_SFILEINFO_UNIX_HLINK:
+ case RAW_SFILEINFO_RENAME_INFORMATION_SMB2:
break;
}
diff --git a/source4/libcli/raw/request.h b/source4/libcli/raw/request.h
index 803a450e3c..2a572e58ee 100644
--- a/source4/libcli/raw/request.h
+++ b/source4/libcli/raw/request.h
@@ -22,11 +22,25 @@
#include "libcli/raw/signing.h"
+#define BUFINFO_FLAG_UNICODE 0x0001
+#define BUFINFO_FLAG_SMB2 0x0002
+
+/*
+ buffer limit structure used by both SMB and SMB2
+ */
+struct request_bufinfo {
+ TALLOC_CTX *mem_ctx;
+ uint32_t flags;
+ const uint8_t *align_base;
+ const uint8_t *data;
+ size_t data_size;
+};
+
/*
Shared state structure between client and server, representing the basic packet.
*/
-struct request_buffer {
+struct smb_request_buffer {
/* the raw SMB buffer, including the 4 byte length header */
uint8_t *buffer;
@@ -56,6 +70,9 @@ struct request_buffer {
* a send packet is done we need to move this
* pointer */
uint8_t *ptr;
+
+ /* this is used to range check and align strings and buffers */
+ struct request_bufinfo bufinfo;
};
#endif
diff --git a/source4/libcli/raw/smb_signing.c b/source4/libcli/raw/smb_signing.c
index 0053710aaf..4acfb9d16d 100644
--- a/source4/libcli/raw/smb_signing.c
+++ b/source4/libcli/raw/smb_signing.c
@@ -65,7 +65,7 @@ static bool smbcli_set_smb_signing_common(struct smbcli_transport *transport)
return true;
}
-void mark_packet_signed(struct request_buffer *out)
+void mark_packet_signed(struct smb_request_buffer *out)
{
uint16_t flags2;
flags2 = SVAL(out->hdr, HDR_FLG2);
@@ -101,7 +101,7 @@ bool signing_good(struct smb_signing_context *sign_info,
return true;
}
-void sign_outgoing_message(struct request_buffer *out, DATA_BLOB *mac_key, unsigned int seq_num)
+void sign_outgoing_message(struct smb_request_buffer *out, DATA_BLOB *mac_key, unsigned int seq_num)
{
uint8_t calc_md5_mac[16];
struct MD5Context md5_ctx;
@@ -133,7 +133,7 @@ void sign_outgoing_message(struct request_buffer *out, DATA_BLOB *mac_key, unsig
Uncomment this to test if the remote server actually verifies signitures...*/
}
-bool check_signed_incoming_message(struct request_buffer *in, DATA_BLOB *mac_key, uint_t seq_num)
+bool check_signed_incoming_message(struct smb_request_buffer *in, DATA_BLOB *mac_key, uint_t seq_num)
{
bool good;
uint8_t calc_md5_mac[16];
diff --git a/source4/libcli/smb2/cancel.c b/source4/libcli/smb2/cancel.c
index 096919f177..80127feea5 100644
--- a/source4/libcli/smb2/cancel.c
+++ b/source4/libcli/smb2/cancel.c
@@ -52,11 +52,11 @@ NTSTATUS smb2_cancel(struct smb2_request *r)
c->seqnum = 0;
SIVAL(c->out.hdr, SMB2_HDR_FLAGS, 0x00000002);
- SSVAL(c->out.hdr, SMB2_HDR_UNKNOWN1, 0x0030);
+ SSVAL(c->out.hdr, SMB2_HDR_CREDIT, 0x0030);
SIVAL(c->out.hdr, SMB2_HDR_PID, r->cancel.pending_id);
- SBVAL(c->out.hdr, SMB2_HDR_SEQNUM, c->seqnum);
+ SBVAL(c->out.hdr, SMB2_HDR_MESSAGE_ID, c->seqnum);
if (r->session) {
- SBVAL(c->out.hdr, SMB2_HDR_UID, r->session->uid);
+ SBVAL(c->out.hdr, SMB2_HDR_SESSION_ID, r->session->uid);
}
SSVAL(c->out.body, 0x02, 0);
diff --git a/source4/libcli/smb2/connect.c b/source4/libcli/smb2/connect.c
index 4518203183..85ddafc031 100644
--- a/source4/libcli/smb2/connect.c
+++ b/source4/libcli/smb2/connect.c
@@ -73,7 +73,7 @@ static void continue_session(struct composite_context *creq)
state->tree = smb2_tree_init(state->session, state, true);
if (composite_nomem(state->tree, c)) return;
- state->tcon.in.unknown1 = 0x09;
+ state->tcon.in.reserved = 0;
state->tcon.in.path = talloc_asprintf(state, "\\\\%s\\%s",
state->host, state->share);
if (composite_nomem(state->tcon.in.path, c)) return;
@@ -120,6 +120,7 @@ static void continue_socket(struct composite_context *creq)
struct smbcli_socket *sock;
struct smb2_transport *transport;
struct smb2_request *req;
+ uint16_t dialects[1];
c->status = smbcli_sock_connect_recv(creq, state, &sock);
if (!composite_is_ok(c)) return;
@@ -128,7 +129,12 @@ static void continue_socket(struct composite_context *creq)
if (composite_nomem(transport, c)) return;
ZERO_STRUCT(state->negprot);
- state->negprot.in.unknown1 = 0x0001;
+ state->negprot.in.dialect_count = 1;
+ state->negprot.in.security_mode = 0;
+ state->negprot.in.capabilities = 0;
+ unix_to_nt_time(&state->negprot.in.start_time, time(NULL));
+ dialects[0] = SMB2_DIALECT_REVISION;
+ state->negprot.in.dialects = dialects;
req = smb2_negprot_send(transport, &state->negprot);
if (composite_nomem(req, c)) return;
diff --git a/source4/libcli/smb2/create.c b/source4/libcli/smb2/create.c
index ba11c22e87..cca83a040c 100644
--- a/source4/libcli/smb2/create.c
+++ b/source4/libcli/smb2/create.c
@@ -24,34 +24,33 @@
#include "libcli/smb2/smb2.h"
#include "libcli/smb2/smb2_calls.h"
-#define CREATE_TAG_EXTA 0x41747845 /* "ExtA" */
-#define CREATE_TAG_MXAC 0x6341784D /* "MxAc" */
-
/*
add a blob to a smb2_create attribute blob
*/
NTSTATUS smb2_create_blob_add(TALLOC_CTX *mem_ctx, DATA_BLOB *blob,
- uint32_t tag,
+ const char *tag,
DATA_BLOB add, bool last)
{
uint32_t ofs = blob->length;
- uint8_t pad = smb2_padding_size(add.length, 8);
- if (!data_blob_realloc(mem_ctx, blob, blob->length + 0x18 + add.length + pad))
+ size_t tag_length = strlen(tag);
+ uint8_t pad = smb2_padding_size(add.length+tag_length, 8);
+ if (!data_blob_realloc(mem_ctx, blob,
+ blob->length + 0x14 + tag_length + add.length + pad))
return NT_STATUS_NO_MEMORY;
if (last) {
SIVAL(blob->data, ofs+0x00, 0);
} else {
- SIVAL(blob->data, ofs+0x00, 0x18 + add.length + pad);
+ SIVAL(blob->data, ofs+0x00, 0x14 + tag_length + add.length + pad);
}
SSVAL(blob->data, ofs+0x04, 0x10); /* offset of tag */
- SIVAL(blob->data, ofs+0x06, 0x04); /* tag length */
- SSVAL(blob->data, ofs+0x0A, 0x18); /* offset of data */
+ SIVAL(blob->data, ofs+0x06, tag_length); /* tag length */
+ SSVAL(blob->data, ofs+0x0A, 0x14 + tag_length); /* offset of data */
SIVAL(blob->data, ofs+0x0C, add.length);
- SIVAL(blob->data, ofs+0x10, tag);
- SIVAL(blob->data, ofs+0x14, 0); /* pad? */
- memcpy(blob->data+ofs+0x18, add.data, add.length);
- memset(blob->data+ofs+0x18+add.length, 0, pad);
+ memcpy(blob->data+ofs+0x10, tag, tag_length);
+ SIVAL(blob->data, ofs+0x10+tag_length, 0); /* pad? */
+ memcpy(blob->data+ofs+0x14+tag_length, add.data, add.length);
+ memset(blob->data+ofs+0x14+tag_length+add.length, 0, pad);
return NT_STATUS_OK;
}
@@ -68,16 +67,15 @@ struct smb2_request *smb2_create_send(struct smb2_tree *tree, struct smb2_create
req = smb2_request_init_tree(tree, SMB2_OP_CREATE, 0x38, true, 0);
if (req == NULL) return NULL;
- SSVAL(req->out.body, 0x02, io->in.oplock_flags);
- SIVAL(req->out.body, 0x04, io->in.impersonation);
- SIVAL(req->out.body, 0x08, io->in.unknown3[0]);
- SIVAL(req->out.body, 0x0C, io->in.unknown3[1]);
- SIVAL(req->out.body, 0x10, io->in.unknown3[2]);
- SIVAL(req->out.body, 0x14, io->in.unknown3[3]);
- SIVAL(req->out.body, 0x18, io->in.access_mask);
- SIVAL(req->out.body, 0x1C, io->in.file_attr);
+ SCVAL(req->out.body, 0x02, io->in.security_flags);
+ SCVAL(req->out.body, 0x03, io->in.oplock_level);
+ SIVAL(req->out.body, 0x04, io->in.impersonation_level);
+ SBVAL(req->out.body, 0x08, io->in.create_flags);
+ SBVAL(req->out.body, 0x10, io->in.reserved);
+ SIVAL(req->out.body, 0x18, io->in.desired_access);
+ SIVAL(req->out.body, 0x1C, io->in.file_attributes);
SIVAL(req->out.body, 0x20, io->in.share_access);
- SIVAL(req->out.body, 0x24, io->in.open_disposition);
+ SIVAL(req->out.body, 0x24, io->in.create_disposition);
SIVAL(req->out.body, 0x28, io->in.create_options);
status = smb2_push_o16s16_string(&req->out, 0x2C, io->in.fname);
@@ -90,7 +88,7 @@ struct smb2_request *smb2_create_send(struct smb2_tree *tree, struct smb2_create
DATA_BLOB b = data_blob_talloc(req, NULL,
ea_list_size_chained(io->in.eas.num_eas, io->in.eas.eas));
ea_put_list_chained(b.data, io->in.eas.num_eas, io->in.eas.eas);
- status = smb2_create_blob_add(req, &blob, CREATE_TAG_EXTA, b, false);
+ status = smb2_create_blob_add(req, &blob, SMB2_CREATE_TAG_EXTA, b, false);
if (!NT_STATUS_IS_OK(status)) {
talloc_free(req);
return NULL;
@@ -100,7 +98,8 @@ struct smb2_request *smb2_create_send(struct smb2_tree *tree, struct smb2_create
/* an empty MxAc tag seems to be used to ask the server to
return the maximum access mask allowed on the file */
- status = smb2_create_blob_add(req, &blob, CREATE_TAG_MXAC, data_blob(NULL, 0), true);
+ status = smb2_create_blob_add(req, &blob, SMB2_CREATE_TAG_MXAC,
+ data_blob(NULL, 0), true);
if (!NT_STATUS_IS_OK(status)) {
talloc_free(req);
@@ -132,7 +131,8 @@ NTSTATUS smb2_create_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx, struct
SMB2_CHECK_PACKET_RECV(req, 0x58, true);
- io->out.oplock_flags = SVAL(req->in.body, 0x02);
+ io->out.oplock_level = CVAL(req->in.body, 0x02);
+ io->out.reserved = CVAL(req->in.body, 0x03);
io->out.create_action = IVAL(req->in.body, 0x04);
io->out.create_time = smbcli_pull_nttime(req->in.body, 0x08);
io->out.access_time = smbcli_pull_nttime(req->in.body, 0x10);
@@ -141,7 +141,7 @@ NTSTATUS smb2_create_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx, struct
io->out.alloc_size = BVAL(req->in.body, 0x28);
io->out.size = BVAL(req->in.body, 0x30);
io->out.file_attr = IVAL(req->in.body, 0x38);
- io->out._pad = IVAL(req->in.body, 0x3C);
+ io->out.reserved2 = IVAL(req->in.body, 0x3C);
smb2_pull_handle(req->in.body+0x40, &io->out.file.handle);
status = smb2_pull_o32s32_blob(&req->in, mem_ctx, req->in.body+0x50, &io->out.blob);
if (!NT_STATUS_IS_OK(status)) {
diff --git a/source4/libcli/smb2/getinfo.c b/source4/libcli/smb2/getinfo.c
index 0665dd441c..e9f47140f5 100644
--- a/source4/libcli/smb2/getinfo.c
+++ b/source4/libcli/smb2/getinfo.c
@@ -30,21 +30,27 @@
struct smb2_request *smb2_getinfo_send(struct smb2_tree *tree, struct smb2_getinfo *io)
{
struct smb2_request *req;
+ NTSTATUS status;
- req = smb2_request_init_tree(tree, SMB2_OP_GETINFO, 0x28, false, 0);
+ req = smb2_request_init_tree(tree, SMB2_OP_GETINFO, 0x28, true,
+ io->in.blob.length);
if (req == NULL) return NULL;
- /* this seems to be a bug, they use 0x29 but only send 0x28 bytes */
- SSVAL(req->out.body, 0x00, 0x29);
-
- SSVAL(req->out.body, 0x02, io->in.level);
- SIVAL(req->out.body, 0x04, io->in.max_response_size);
- SIVAL(req->out.body, 0x08, io->in.unknown1);
- SIVAL(req->out.body, 0x0C, io->in.unknown2);
- SIVAL(req->out.body, 0x10, io->in.flags);
- SIVAL(req->out.body, 0x14, io->in.flags2);
+ SCVAL(req->out.body, 0x02, io->in.info_type);
+ SCVAL(req->out.body, 0x03, io->in.info_class);
+ SIVAL(req->out.body, 0x04, io->in.output_buffer_length);
+ SIVAL(req->out.body, 0x0C, io->in.reserved);
+ SIVAL(req->out.body, 0x08, io->in.input_buffer_length);
+ SIVAL(req->out.body, 0x10, io->in.additional_information);
+ SIVAL(req->out.body, 0x14, io->in.getinfo_flags);
smb2_push_handle(req->out.body+0x18, &io->in.file.handle);
+ /* this blob is used for quota queries */
+ status = smb2_push_o32s32_blob(&req->out, 0x08, io->in.blob);
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(req);
+ return NULL;
+ }
smb2_transport_send(req);
return req;
@@ -116,15 +122,17 @@ struct smb2_request *smb2_getinfo_file_send(struct smb2_tree *tree, union smb_fi
}
ZERO_STRUCT(b);
- b.in.max_response_size = 0x10000;
- b.in.file.handle = io->generic.in.file.handle;
- b.in.level = smb2_level;
+ b.in.info_type = smb2_level & 0xFF;
+ b.in.info_class = smb2_level >> 8;
+ b.in.output_buffer_length = 0x10000;
+ b.in.input_buffer_length = 0;
+ b.in.file.handle = io->generic.in.file.handle;
if (io->generic.level == RAW_FILEINFO_SEC_DESC) {
- b.in.flags = io->query_secdesc.in.secinfo_flags;
+ b.in.additional_information = io->query_secdesc.in.secinfo_flags;
}
if (io->generic.level == RAW_FILEINFO_SMB2_ALL_EAS) {
- b.in.flags2 = io->all_eas.in.continue_flags;
+ b.in.getinfo_flags = io->all_eas.in.continue_flags;
}
return smb2_getinfo_send(tree, &b);
@@ -172,9 +180,10 @@ struct smb2_request *smb2_getinfo_fs_send(struct smb2_tree *tree, union smb_fsin
}
ZERO_STRUCT(b);
- b.in.max_response_size = 0x10000;
- b.in.file.handle = io->generic.handle;
- b.in.level = smb2_level;
+ b.in.output_buffer_length = 0x10000;
+ b.in.file.handle = io->generic.handle;
+ b.in.info_type = smb2_level & 0xFF;
+ b.in.info_class = smb2_level >> 8;
return smb2_getinfo_send(tree, &b);
}
diff --git a/source4/libcli/smb2/logoff.c b/source4/libcli/smb2/logoff.c
index 321a4db1a6..b38a08ca43 100644
--- a/source4/libcli/smb2/logoff.c
+++ b/source4/libcli/smb2/logoff.c
@@ -33,7 +33,7 @@ struct smb2_request *smb2_logoff_send(struct smb2_session *session)
req = smb2_request_init(session->transport, SMB2_OP_LOGOFF, 0x04, false, 0);
if (req == NULL) return NULL;
- SBVAL(req->out.hdr, SMB2_HDR_UID, session->uid);
+ SBVAL(req->out.hdr, SMB2_HDR_SESSION_ID, session->uid);
SSVAL(req->out.body, 0x02, 0);
diff --git a/source4/libcli/smb2/negprot.c b/source4/libcli/smb2/negprot.c
index 38fe0e7e53..6b879e2add 100644
--- a/source4/libcli/smb2/negprot.c
+++ b/source4/libcli/smb2/negprot.c
@@ -31,16 +31,28 @@ struct smb2_request *smb2_negprot_send(struct smb2_transport *transport,
struct smb2_negprot *io)
{
struct smb2_request *req;
-
- req = smb2_request_init(transport, SMB2_OP_NEGPROT, 0x26, false, 0);
+ uint16_t size = 0x24 + io->in.dialect_count*2;
+ enum ndr_err_code ndr_err;
+ int i;
+
+ req = smb2_request_init(transport, SMB2_OP_NEGPROT, size, false, 0);
if (req == NULL) return NULL;
- /* this seems to be a bug, they use 0x24 but the length is 0x26 */
- SSVAL(req->out.body, 0x00, 0x24);
- SSVAL(req->out.body, 0x02, io->in.unknown1);
- memcpy(req->out.body+0x04, io->in.unknown2, 32);
- SSVAL(req->out.body, 0x24, io->in.unknown3);
+ SSVAL(req->out.body, 0x00, 0x24);
+ SSVAL(req->out.body, 0x02, io->in.dialect_count);
+ SSVAL(req->out.body, 0x04, io->in.security_mode);
+ SSVAL(req->out.body, 0x06, io->in.reserved);
+ SIVAL(req->out.body, 0x08, io->in.capabilities);
+ ndr_err = smbcli_push_guid(req->out.body, 0x0C, &io->in.client_guid);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ talloc_free(req);
+ return NULL;
+ }
+ smbcli_push_nttime(req->out.body, 0x1C, io->in.start_time);
+ for (i=0;i<io->in.dialect_count;i++) {
+ SSVAL(req->out.body, 0x24 + i*2, io->in.dialects[i]);
+ }
smb2_transport_send(req);
@@ -54,6 +66,7 @@ NTSTATUS smb2_negprot_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx,
struct smb2_negprot *io)
{
NTSTATUS status;
+ enum ndr_err_code ndr_err;
if (!smb2_request_receive(req) ||
smb2_request_is_error(req)) {
@@ -62,24 +75,27 @@ NTSTATUS smb2_negprot_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx,
SMB2_CHECK_PACKET_RECV(req, 0x40, true);
- io->out._pad = SVAL(req->in.body, 0x02);
- io->out.unknown2 = IVAL(req->in.body, 0x04);
- memcpy(io->out.sessid, req->in.body + 0x08, 16);
- io->out.unknown3 = IVAL(req->in.body, 0x18);
- io->out.unknown4 = SVAL(req->in.body, 0x1C);
- io->out.unknown5 = IVAL(req->in.body, 0x1E);
- io->out.unknown6 = IVAL(req->in.body, 0x22);
- io->out.unknown7 = SVAL(req->in.body, 0x26);
- io->out.current_time = smbcli_pull_nttime(req->in.body, 0x28);
- io->out.boot_time = smbcli_pull_nttime(req->in.body, 0x30);
+ io->out.security_mode = SVAL(req->in.body, 0x02);
+ io->out.dialect_revision = SVAL(req->in.body, 0x04);
+ io->out.reserved = SVAL(req->in.body, 0x06);
+ ndr_err = smbcli_pull_guid(req->in.body, 0x08, &io->in.client_guid);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ smb2_request_destroy(req);
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+ io->out.capabilities = IVAL(req->in.body, 0x18);
+ io->out.max_transact_size = IVAL(req->in.body, 0x1C);
+ io->out.max_read_size = IVAL(req->in.body, 0x20);
+ io->out.max_write_size = IVAL(req->in.body, 0x24);
+ io->out.system_time = smbcli_pull_nttime(req->in.body, 0x28);
+ io->out.server_start_time = smbcli_pull_nttime(req->in.body, 0x30);
+ io->out.reserved2 = IVAL(req->in.body, 0x3C);
status = smb2_pull_o16s16_blob(&req->in, mem_ctx, req->in.body+0x38, &io->out.secblob);
if (!NT_STATUS_IS_OK(status)) {
smb2_request_destroy(req);
return status;
}
-
- io->out.unknown9 = IVAL(req->in.body, 0x3C);
return smb2_request_destroy(req);
}
diff --git a/source4/libcli/smb2/notify.c b/source4/libcli/smb2/notify.c
index a3bea41eb0..e7c38a27f9 100644
--- a/source4/libcli/smb2/notify.c
+++ b/source4/libcli/smb2/notify.c
@@ -35,7 +35,7 @@ struct smb2_request *smb2_notify_send(struct smb2_tree *tree, struct smb2_notify
req = smb2_request_init_tree(tree, SMB2_OP_NOTIFY, 0x20, false, 0);
if (req == NULL) return NULL;
- SSVAL(req->out.hdr, SMB2_HDR_UNKNOWN1, 0x0030);
+ SSVAL(req->out.hdr, SMB2_HDR_CREDIT, 0x0030);
SSVAL(req->out.body, 0x02, io->in.recursive);
SIVAL(req->out.body, 0x04, io->in.buffer_size);
diff --git a/source4/libcli/smb2/request.c b/source4/libcli/smb2/request.c
index 73c74dcfeb..2471fcaa4d 100644
--- a/source4/libcli/smb2/request.c
+++ b/source4/libcli/smb2/request.c
@@ -28,6 +28,21 @@
#include "libcli/smb2/smb2_calls.h"
#include "param/param.h"
+/* fill in the bufinfo */
+void smb2_setup_bufinfo(struct smb2_request *req)
+{
+ req->in.bufinfo.mem_ctx = req;
+ req->in.bufinfo.flags = BUFINFO_FLAG_UNICODE | BUFINFO_FLAG_SMB2;
+ req->in.bufinfo.align_base = req->in.buffer;
+ if (req->in.dynamic) {
+ req->in.bufinfo.data = req->in.dynamic;
+ req->in.bufinfo.data_size = req->in.body_size - req->in.body_fixed;
+ } else {
+ req->in.bufinfo.data = NULL;
+ req->in.bufinfo.data_size = 0;
+ }
+}
+
/*
initialise a smb2 request
*/
@@ -83,17 +98,17 @@ struct smb2_request *smb2_request_init(struct smb2_transport *transport, uint16_
SIVAL(req->out.hdr, 0, SMB2_MAGIC);
SSVAL(req->out.hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
- SSVAL(req->out.hdr, SMB2_HDR_PAD1, 0);
+ SSVAL(req->out.hdr, SMB2_HDR_EPOCH, 0);
SIVAL(req->out.hdr, SMB2_HDR_STATUS, 0);
SSVAL(req->out.hdr, SMB2_HDR_OPCODE, opcode);
- SSVAL(req->out.hdr, SMB2_HDR_UNKNOWN1, 0);
+ SSVAL(req->out.hdr, SMB2_HDR_CREDIT, 0);
SIVAL(req->out.hdr, SMB2_HDR_FLAGS, 0);
- SIVAL(req->out.hdr, SMB2_HDR_CHAIN_OFFSET, 0);
- SBVAL(req->out.hdr, SMB2_HDR_SEQNUM, req->seqnum);
+ SIVAL(req->out.hdr, SMB2_HDR_NEXT_COMMAND, 0);
+ SBVAL(req->out.hdr, SMB2_HDR_MESSAGE_ID, req->seqnum);
SIVAL(req->out.hdr, SMB2_HDR_PID, 0);
SIVAL(req->out.hdr, SMB2_HDR_TID, 0);
- SBVAL(req->out.hdr, SMB2_HDR_UID, 0);
- memset(req->out.hdr+SMB2_HDR_SIG, 0, 16);
+ SBVAL(req->out.hdr, SMB2_HDR_SESSION_ID, 0);
+ memset(req->out.hdr+SMB2_HDR_SIGNATURE, 0, 16);
/* set the length of the fixed body part and +1 if there's a dynamic part also */
SSVAL(req->out.body, 0, body_fixed_size + (body_dynamic_size?1:0));
@@ -122,7 +137,7 @@ struct smb2_request *smb2_request_init_tree(struct smb2_tree *tree, uint16_t opc
body_dynamic_size);
if (req == NULL) return NULL;
- SBVAL(req->out.hdr, SMB2_HDR_UID, tree->session->uid);
+ SBVAL(req->out.hdr, SMB2_HDR_SESSION_ID, tree->session->uid);
SIVAL(req->out.hdr, SMB2_HDR_TID, tree->tid);
req->session = tree->session;
req->tree = tree;
@@ -191,6 +206,10 @@ bool smb2_request_is_ok(struct smb2_request *req)
*/
bool smb2_oob(struct smb2_request_buffer *buf, const uint8_t *ptr, size_t size)
{
+ if (size == 0) {
+ /* zero bytes is never out of range */
+ return false;
+ }
/* be careful with wraparound! */
if (ptr < buf->body ||
ptr >= buf->body + buf->body_size ||
@@ -255,7 +274,7 @@ NTSTATUS smb2_pull_o16s16_blob(struct smb2_request_buffer *buf, TALLOC_CTX *mem_
}
ofs = SVAL(ptr, 0);
size = SVAL(ptr, 2);
- if (ofs == 0 || size == 0) {
+ if (ofs == 0) {
*blob = data_blob(NULL, 0);
return NT_STATUS_OK;
}
@@ -295,7 +314,10 @@ NTSTATUS smb2_push_o16s16_blob(struct smb2_request_buffer *buf,
return NT_STATUS_BUFFER_TOO_SMALL;
}
- if (blob.length == 0) {
+ if (blob.data == NULL) {
+ if (blob.length != 0) {
+ return NT_STATUS_INTERNAL_ERROR;
+ }
SSVAL(ptr, 0, 0);
SSVAL(ptr, 2, 0);
return NT_STATUS_OK;
@@ -348,7 +370,10 @@ NTSTATUS smb2_push_o16s32_blob(struct smb2_request_buffer *buf,
return NT_STATUS_BUFFER_TOO_SMALL;
}
- if (blob.length == 0) {
+ if (blob.data == NULL) {
+ if (blob.length != 0) {
+ return NT_STATUS_INTERNAL_ERROR;
+ }
SSVAL(ptr, 0, 0);
SIVAL(ptr, 2, 0);
return NT_STATUS_OK;
@@ -401,7 +426,10 @@ NTSTATUS smb2_push_o32s32_blob(struct smb2_request_buffer *buf,
return NT_STATUS_BUFFER_TOO_SMALL;
}
- if (blob.length == 0) {
+ if (blob.data == NULL) {
+ if (blob.length != 0) {
+ return NT_STATUS_INTERNAL_ERROR;
+ }
SIVAL(ptr, 0, 0);
SIVAL(ptr, 4, 0);
return NT_STATUS_OK;
@@ -454,7 +482,10 @@ NTSTATUS smb2_push_s32o32_blob(struct smb2_request_buffer *buf,
return NT_STATUS_BUFFER_TOO_SMALL;
}
- if (blob.length == 0) {
+ if (blob.data == NULL) {
+ if (blob.length != 0) {
+ return NT_STATUS_INTERNAL_ERROR;
+ }
SIVAL(ptr, 0, 0);
SIVAL(ptr, 4, 0);
return NT_STATUS_OK;
@@ -497,7 +528,7 @@ NTSTATUS smb2_pull_o16s32_blob(struct smb2_request_buffer *buf, TALLOC_CTX *mem_
}
ofs = SVAL(ptr, 0);
size = IVAL(ptr, 2);
- if (ofs == 0 || size == 0) {
+ if (ofs == 0) {
*blob = data_blob(NULL, 0);
return NT_STATUS_OK;
}
@@ -521,7 +552,34 @@ NTSTATUS smb2_pull_o32s32_blob(struct smb2_request_buffer *buf, TALLOC_CTX *mem_
}
ofs = IVAL(ptr, 0);
size = IVAL(ptr, 4);
- if (ofs == 0 || size == 0) {
+ if (ofs == 0) {
+ *blob = data_blob(NULL, 0);
+ return NT_STATUS_OK;
+ }
+ if (smb2_oob(buf, buf->hdr + ofs, size)) {
+ return NT_STATUS_BUFFER_TOO_SMALL;
+ }
+ *blob = data_blob_talloc(mem_ctx, buf->hdr + ofs, size);
+ NT_STATUS_HAVE_NO_MEMORY(blob->data);
+ return NT_STATUS_OK;
+}
+
+/*
+ pull a uint16_t ofs/ uint32_t length/blob triple from a data blob
+ the ptr points to the start of the offset/length pair
+
+ In this varient the uint16_t is padded by an extra 2 bytes, making
+ the size aligned on 4 byte boundary
+*/
+NTSTATUS smb2_pull_o16As32_blob(struct smb2_request_buffer *buf, TALLOC_CTX *mem_ctx, uint8_t *ptr, DATA_BLOB *blob)
+{
+ uint32_t ofs, size;
+ if (smb2_oob(buf, ptr, 8)) {
+ return NT_STATUS_BUFFER_TOO_SMALL;
+ }
+ ofs = SVAL(ptr, 0);
+ size = IVAL(ptr, 4);
+ if (ofs == 0) {
*blob = data_blob(NULL, 0);
return NT_STATUS_OK;
}
@@ -545,7 +603,7 @@ NTSTATUS smb2_pull_s32o32_blob(struct smb2_request_buffer *buf, TALLOC_CTX *mem_
}
size = IVAL(ptr, 0);
ofs = IVAL(ptr, 4);
- if (ofs == 0 || size == 0) {
+ if (ofs == 0) {
*blob = data_blob(NULL, 0);
return NT_STATUS_OK;
}
@@ -572,6 +630,11 @@ NTSTATUS smb2_pull_o16s16_string(struct smb2_request_buffer *buf, TALLOC_CTX *me
status = smb2_pull_o16s16_blob(buf, mem_ctx, ptr, &blob);
NT_STATUS_NOT_OK_RETURN(status);
+ if (blob.data == NULL) {
+ *str = NULL;
+ return NT_STATUS_OK;
+ }
+
if (blob.length == 0) {
char *s;
s = talloc_strdup(mem_ctx, "");
@@ -601,10 +664,16 @@ NTSTATUS smb2_push_o16s16_string(struct smb2_request_buffer *buf,
NTSTATUS status;
ssize_t size;
- if (strcmp("", str) == 0) {
+ if (str == NULL) {
return smb2_push_o16s16_blob(buf, ofs, data_blob(NULL, 0));
}
+ if (*str == 0) {
+ blob.data = str;
+ blob.length = 0;
+ return smb2_push_o16s16_blob(buf, ofs, blob);
+ }
+
size = convert_string_talloc(buf->buffer, lp_iconv_convenience(global_loadparm), CH_UNIX, CH_UTF16,
str, strlen(str), (void **)&blob.data);
if (size == -1) {
diff --git a/source4/libcli/smb2/session.c b/source4/libcli/smb2/session.c
index a784ea65d8..18fe3486a4 100644
--- a/source4/libcli/smb2/session.c
+++ b/source4/libcli/smb2/session.c
@@ -74,10 +74,12 @@ struct smb2_request *smb2_session_setup_send(struct smb2_session *session,
0x18, true, io->in.secblob.length);
if (req == NULL) return NULL;
- SBVAL(req->out.hdr, SMB2_HDR_UID, session->uid);
- SSVAL(req->out.body, 0x02, io->in._pad); /* pad */
- SIVAL(req->out.body, 0x04, io->in.unknown2);
- SIVAL(req->out.body, 0x08, io->in.unknown3);
+ SBVAL(req->out.hdr, SMB2_HDR_SESSION_ID, session->uid);
+ SCVAL(req->out.body, 0x02, io->in.vc_number);
+ SCVAL(req->out.body, 0x03, io->in.security_mode);
+ SIVAL(req->out.body, 0x04, io->in.capabilities);
+ SIVAL(req->out.body, 0x08, io->in.channel);
+ SBVAL(req->out.body, 0x10, io->in.previous_sessionid);
req->session = session;
@@ -86,7 +88,6 @@ struct smb2_request *smb2_session_setup_send(struct smb2_session *session,
talloc_free(req);
return NULL;
}
- SBVAL(req->out.body, 0x10, io->in.unknown4);
smb2_transport_send(req);
@@ -110,8 +111,8 @@ NTSTATUS smb2_session_setup_recv(struct smb2_request *req, TALLOC_CTX *mem_ctx,
SMB2_CHECK_PACKET_RECV(req, 0x08, true);
- io->out._pad = SVAL(req->in.body, 0x02);
- io->out.uid = BVAL(req->in.hdr, SMB2_HDR_UID);
+ io->out.session_flags = SVAL(req->in.body, 0x02);
+ io->out.uid = BVAL(req->in.hdr, SMB2_HDR_SESSION_ID);
status = smb2_pull_o16s16_blob(&req->in, mem_ctx, req->in.body+0x04, &io->out.secblob);
if (!NT_STATUS_IS_OK(status)) {
@@ -206,10 +207,11 @@ struct composite_context *smb2_session_setup_spnego_send(struct smb2_session *se
c->private_data = state;
ZERO_STRUCT(state->io);
- state->io.in._pad = 0x0000;
- state->io.in.unknown2 = 0x0000000F;
- state->io.in.unknown3 = 0x00000000;
- state->io.in.unknown4 = 0; /* uint64_t */
+ state->io.in.vc_number = 0;
+ state->io.in.security_mode = 0;
+ state->io.in.capabilities = 0;
+ state->io.in.channel = 0;
+ state->io.in.previous_sessionid = 0;
c->status = gensec_set_credentials(session->gensec, credentials);
if (!composite_is_ok(c)) return c;
diff --git a/source4/libcli/smb2/setinfo.c b/source4/libcli/smb2/setinfo.c
index d942568a2d..a6e22d9a68 100644
--- a/source4/libcli/smb2/setinfo.c
+++ b/source4/libcli/smb2/setinfo.c
@@ -92,6 +92,12 @@ struct smb2_request *smb2_setinfo_file_send(struct smb2_tree *tree, union smb_se
ZERO_STRUCT(b);
b.in.level = smb2_level;
b.in.file.handle = io->generic.in.file.handle;
+
+ /* change levels so the parsers know it is SMB2 */
+ if (io->generic.level == RAW_SFILEINFO_RENAME_INFORMATION) {
+ io->generic.level = RAW_SFILEINFO_RENAME_INFORMATION_SMB2;
+ }
+
if (!smb_raw_setfileinfo_passthru(tree, io->generic.level, io, &b.in.blob)) {
return NULL;
}
diff --git a/source4/libcli/smb2/smb2.h b/source4/libcli/smb2/smb2.h
index 33876c6f7c..726df64090 100644
--- a/source4/libcli/smb2/smb2.h
+++ b/source4/libcli/smb2/smb2.h
@@ -19,6 +19,8 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include "libcli/raw/request.h"
+
struct smb2_options {
uint32_t timeout;
};
@@ -102,6 +104,9 @@ struct smb2_request_buffer {
* this will be moved when some dynamic data is pushed
*/
uint8_t *dynamic;
+
+ /* this is used to range check and align strings and buffers */
+ struct request_bufinfo bufinfo;
};
@@ -156,19 +161,20 @@ struct smb2_request {
#define SMB2_MIN_SIZE 0x42
-/* offsets into header elements */
+/* offsets into header elements for a sync SMB2 request */
+#define SMB2_HDR_PROTOCOL_ID 0x00
#define SMB2_HDR_LENGTH 0x04
-#define SMB2_HDR_PAD1 0x06
+#define SMB2_HDR_EPOCH 0x06
#define SMB2_HDR_STATUS 0x08
#define SMB2_HDR_OPCODE 0x0c
-#define SMB2_HDR_UNKNOWN1 0x0e
+#define SMB2_HDR_CREDIT 0x0e
#define SMB2_HDR_FLAGS 0x10
-#define SMB2_HDR_CHAIN_OFFSET 0x14
-#define SMB2_HDR_SEQNUM 0x18
+#define SMB2_HDR_NEXT_COMMAND 0x14
+#define SMB2_HDR_MESSAGE_ID 0x18
#define SMB2_HDR_PID 0x20
#define SMB2_HDR_TID 0x24
-#define SMB2_HDR_UID 0x28 /* 64 bit */
-#define SMB2_HDR_SIG 0x30 /* guess ... */
+#define SMB2_HDR_SESSION_ID 0x28
+#define SMB2_HDR_SIGNATURE 0x30 /* 16 bytes */
#define SMB2_HDR_BODY 0x40
/* SMB2 opcodes */
@@ -194,6 +200,59 @@ struct smb2_request {
#define SMB2_MAGIC 0x424D53FE /* 0xFE 'S' 'M' 'B' */
+/* the dialect we support */
+#define SMB2_DIALECT_REVISION 0x202
+
+/* SMB2 negotiate security_mode */
+#define SMB2_NEGOTIATE_SIGNING_ENABLED 0x01
+#define SMB2_NEGOTIATE_SIGNING_REQUIRED 0x02
+
+/* SMB2 capabilities - only 1 so far. I'm sure more will be added */
+#define SMB2_CAP_DFS 0x0
+/* so we can spot new caps as added */
+#define SMB2_CAP_ALL SMB2_CAP_DFS
+
+/* SMB2 share flags */
+#define SMB2_SHAREFLAG_MANUAL_CACHING 0x0000
+#define SMB2_SHAREFLAG_AUTO_CACHING 0x0010
+#define SMB2_SHAREFLAG_VDO_CACHING 0x0020
+#define SMB2_SHAREFLAG_NO_CACHING 0x0030
+#define SMB2_SHAREFLAG_DFS 0x0001
+#define SMB2_SHAREFLAG_DFS_ROOT 0x0002
+#define SMB2_SHAREFLAG_RESTRICT_EXCLUSIVE_OPENS 0x0100
+#define SMB2_SHAREFLAG_FORCE_SHARED_DELETE 0x0200
+#define SMB2_SHAREFLAG_ALLOW_NAMESPACE_CACHING 0x0400
+#define SMB2_SHAREFLAG_ACCESS_BASED_DIRECTORY_ENUM 0x0800
+#define SMB2_SHAREFLAG_ALL 0x0F33
+
+/* SMB2 create security flags */
+#define SMB2_SECURITY_DYNAMIC_TRACKING 0x01
+#define SMB2_SECURITY_EFFECTIVE_ONLY 0x02
+
+/* SMB2 requested oplock levels */
+#define SMB2_OPLOCK_LEVEL_NONE 0x00
+#define SMB2_OPLOCK_LEVEL_II 0x01
+#define SMB2_OPLOCK_LEVEL_EXCLUSIVE 0x08
+#define SMB2_OPLOCK_LEVEL_BATCH 0x09
+
+/* SMB2 impersonation levels */
+#define SMB2_IMPERSONATION_ANONYMOUS 0x00
+#define SMB2_IMPERSONATION_IDENTIFICATION 0x01
+#define SMB2_IMPERSONATION_IMPERSONATION 0x02
+#define SMB2_IMPERSONATION_DELEGATE 0x03
+
+/* SMB2 create tags */
+#define SMB2_CREATE_TAG_EXTA "ExtA"
+#define SMB2_CREATE_TAG_MXAC "MxAc"
+#define SMB2_CREATE_TAG_SECD "SecD"
+#define SMB2_CREATE_TAG_DHNQ "DHnQ"
+#define SMB2_CREATE_TAG_DHNC "DHnC"
+#define SMB2_CREATE_TAG_ALSI "AlSi"
+#define SMB2_CREATE_TAG_TWRP "TWrp"
+#define SMB2_CREATE_TAG_QFID "QFid"
+
+
+
/*
check that a body has the expected size
*/
diff --git a/source4/libcli/smb2/smb2_calls.h b/source4/libcli/smb2/smb2_calls.h
index 6a551da4ae..f66236af30 100644
--- a/source4/libcli/smb2/smb2_calls.h
+++ b/source4/libcli/smb2/smb2_calls.h
@@ -23,30 +23,31 @@
struct smb2_negprot {
struct {
- /* static body buffer 38 (0x26) bytes */
- /* uint16_t buffer_code; 0x24 (why?) */
- uint16_t unknown1; /* 0x0001 */
- uint8_t unknown2[32]; /* all zero */
- uint16_t unknown3; /* 0x00000 */
+ uint16_t dialect_count; /* size of dialects array */
+ uint16_t security_mode; /* 0==signing disabled
+ 1==signing enabled */
+ uint16_t reserved;
+ uint32_t capabilities;
+ struct GUID client_guid;
+ NTTIME start_time;
+ uint16_t *dialects;
} in;
struct {
/* static body buffer 64 (0x40) bytes */
/* uint16_t buffer_code; 0x41 = 0x40 + 1 */
- uint16_t _pad;
- uint32_t unknown2; /* 0x06 */
- uint8_t sessid[16];
- uint32_t unknown3; /* 0x0d */
- uint16_t unknown4; /* 0x00 */
- uint32_t unknown5; /* 0x01 */
- uint32_t unknown6; /* 0x01 */
- uint16_t unknown7; /* 0x01 */
- NTTIME current_time;
- NTTIME boot_time;
+ uint16_t security_mode; /* SMB2_NEGOTIATE_SIGNING_* */
+ uint16_t dialect_revision;
+ uint16_t reserved;
+ struct GUID server_guid;
+ uint32_t capabilities;
+ uint32_t max_transact_size;
+ uint32_t max_read_size;
+ uint32_t max_write_size;
+ NTTIME system_time;
+ NTTIME server_start_time;
/* uint16_t secblob_ofs */
/* uint16_t secblob_size */
- uint32_t unknown9; /* 0x204d4c20 */
-
- /* dynamic body buffer */
+ uint32_t reserved2;
DATA_BLOB secblob;
} out;
};
@@ -55,6 +56,13 @@ struct smb2_negprot {
#define SMB2_GETINFO_FILE 0x01
#define SMB2_GETINFO_FS 0x02
#define SMB2_GETINFO_SECURITY 0x03
+#define SMB2_GETINFO_QUOTA 0x04
+
+#define SMB2_GETINFO_ADD_OWNER_SECURITY 0x01
+#define SMB2_GETINFO_ADD_GROUP_SECURITY 0x02
+#define SMB2_GETINFO_ADD_DACL_SECURITY 0x04
+#define SMB2_GETINFO_ADD_SACL_SECURITY 0x08
+#define SMB2_GETINFO_ADD_LABEL_SECURITY 0x10
/* NOTE! the getinfo fs and file levels exactly match up with the
'passthru' SMB levels, which are levels >= 1000. The SMB2 client
@@ -63,14 +71,17 @@ struct smb2_negprot {
struct smb2_getinfo {
struct {
/* static body buffer 40 (0x28) bytes */
- /* uint16_t buffer_code; 0x29 = 0x28 + 1 (why???) */
- uint16_t level;
- uint32_t max_response_size;
- uint32_t unknown1;
- uint32_t unknown2;
- uint32_t flags; /* level specific */
- uint32_t flags2; /* used by all_eas level */
+ /* uint16_t buffer_code; 0x29 = 0x28 + 1 */
+ uint8_t info_type;
+ uint8_t info_class;
+ uint32_t output_buffer_length;
+ /* uint32_t input_buffer_offset; */
+ uint32_t reserved;
+ uint32_t input_buffer_length;
+ uint32_t additional_information; /* SMB2_GETINFO_ADD_* */
+ uint32_t getinfo_flags; /* level specific */
union smb_handle file;
+ DATA_BLOB blob;
} in;
struct {
diff --git a/source4/libcli/smb2/tcon.c b/source4/libcli/smb2/tcon.c
index ad1ba4c92d..db35669d41 100644
--- a/source4/libcli/smb2/tcon.c
+++ b/source4/libcli/smb2/tcon.c
@@ -56,9 +56,9 @@ struct smb2_request *smb2_tree_connect_send(struct smb2_tree *tree,
0x08, true, 0);
if (req == NULL) return NULL;
- SBVAL(req->out.hdr, SMB2_HDR_UID, tree->session->uid);
+ SBVAL(req->out.hdr, SMB2_HDR_SESSION_ID, tree->session->uid);
- SSVAL(req->out.body, 0x02, io->in.unknown1);
+ SSVAL(req->out.body, 0x02, io->in.reserved);
status = smb2_push_o16s16_string(&req->out, 0x04, io->in.path);
if (!NT_STATUS_IS_OK(status)) {
talloc_free(req);
@@ -85,10 +85,18 @@ NTSTATUS smb2_tree_connect_recv(struct smb2_request *req, struct smb2_tree_conne
io->out.tid = IVAL(req->in.hdr, SMB2_HDR_TID);
- io->out.unknown1 = SVAL(req->in.body, 0x02);
- io->out.unknown2 = IVAL(req->in.body, 0x04);
- io->out.unknown3 = IVAL(req->in.body, 0x08);
+ io->out.share_type = CVAL(req->in.body, 0x02);
+ io->out.reserved = CVAL(req->in.body, 0x03);
+ io->out.flags = IVAL(req->in.body, 0x04);
+ io->out.capabilities= IVAL(req->in.body, 0x08);
io->out.access_mask = IVAL(req->in.body, 0x0C);
+
+ if (io->out.capabilities & ~SMB2_CAP_ALL) {
+ DEBUG(0,("Unknown capabilities mask 0x%x\n", io->out.capabilities));
+ }
+ if (io->out.flags & ~SMB2_SHAREFLAG_ALL) {
+ DEBUG(0,("Unknown tcon shareflag 0x%x\n", io->out.flags));
+ }
return smb2_request_destroy(req);
}
diff --git a/source4/libcli/smb2/transport.c b/source4/libcli/smb2/transport.c
index 83e9436a58..1d601fdbfe 100644
--- a/source4/libcli/smb2/transport.c
+++ b/source4/libcli/smb2/transport.c
@@ -167,7 +167,7 @@ static NTSTATUS smb2_transport_finish_recv(void *private, DATA_BLOB blob)
}
flags = IVAL(hdr, SMB2_HDR_FLAGS);
- seqnum = BVAL(hdr, SMB2_HDR_SEQNUM);
+ seqnum = BVAL(hdr, SMB2_HDR_MESSAGE_ID);
/* match the incoming request against the list of pending requests */
for (req=transport->pending_recv; req; req=req->next) {
@@ -216,6 +216,8 @@ static NTSTATUS smb2_transport_finish_recv(void *private, DATA_BLOB blob)
}
}
+ smb2_setup_bufinfo(req);
+
DEBUG(2, ("SMB2 RECV seqnum=0x%llx\n", (long long)req->seqnum));
dump_data(5, req->in.body, req->in.body_size);