From b0f34bc8ca072c06b89934fbef516a2f3da0e269 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 16 Apr 2008 10:05:53 +0200 Subject: libcli/smb2: also offer the SMB2 dialect that what used in longhorn beta3 With this smbtorture works against longhorn beta3 again, hopefully it still works with new versions... metze (This used to be commit 874924a85a862e38b7d1a6199276e998cf3697d8) --- source4/libcli/smb2/connect.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source4/libcli/smb2') diff --git a/source4/libcli/smb2/connect.c b/source4/libcli/smb2/connect.c index d68b85ad54..59d4e6ea2d 100644 --- a/source4/libcli/smb2/connect.c +++ b/source4/libcli/smb2/connect.c @@ -121,7 +121,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]; + uint16_t dialects[2]; c->status = smbcli_sock_connect_recv(creq, state, &sock); if (!composite_is_ok(c)) return; @@ -130,11 +130,12 @@ static void continue_socket(struct composite_context *creq) if (composite_nomem(transport, c)) return; ZERO_STRUCT(state->negprot); - state->negprot.in.dialect_count = 1; + state->negprot.in.dialect_count = 2; 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; + dialects[0] = 0; + dialects[1] = SMB2_DIALECT_REVISION; state->negprot.in.dialects = dialects; req = smb2_negprot_send(transport, &state->negprot); -- cgit From 578539216fcb275e5ec013b3ed1c81e4baced80e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 16 Apr 2008 10:03:08 +0200 Subject: libcli/smb2: make it possible to pass additional extra blobs in smb2_create() This also fixes the alignment from 8 to 4 byte bounderies. metze (This used to be commit e0a0d8e36acd735b587cd7870625af52c5dc3431) --- source4/libcli/smb2/create.c | 94 +++++++++++++++++++++++++++++++++----------- 1 file changed, 71 insertions(+), 23 deletions(-) (limited to 'source4/libcli/smb2') diff --git a/source4/libcli/smb2/create.c b/source4/libcli/smb2/create.c index 999c10ab08..6ac32a494f 100644 --- a/source4/libcli/smb2/create.c +++ b/source4/libcli/smb2/create.c @@ -28,30 +28,59 @@ /* add a blob to a smb2_create attribute blob */ -NTSTATUS smb2_create_blob_add(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, - const char *tag, - DATA_BLOB add, bool last) +static NTSTATUS smb2_create_blob_push_one(TALLOC_CTX *mem_ctx, DATA_BLOB *buffer, + const struct smb2_create_blob *blob, + bool last) { - uint32_t ofs = blob->length; - 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)) + uint32_t ofs = buffer->length; + size_t tag_length = strlen(blob->tag); + uint8_t pad = smb2_padding_size(blob->data.length+tag_length, 4); + + if (!data_blob_realloc(mem_ctx, buffer, + buffer->length + 0x14 + tag_length + blob->data.length + pad)) return NT_STATUS_NO_MEMORY; - + if (last) { - SIVAL(blob->data, ofs+0x00, 0); + SIVAL(buffer->data, ofs+0x00, 0); } else { - SIVAL(blob->data, ofs+0x00, 0x14 + tag_length + add.length + pad); + SIVAL(buffer->data, ofs+0x00, 0x14 + tag_length + blob->data.length + pad); } - SSVAL(blob->data, ofs+0x04, 0x10); /* offset of tag */ - 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); - 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); + SSVAL(buffer->data, ofs+0x04, 0x10); /* offset of tag */ + SIVAL(buffer->data, ofs+0x06, tag_length); /* tag length */ + SSVAL(buffer->data, ofs+0x0A, 0x14 + tag_length); /* offset of data */ + SIVAL(buffer->data, ofs+0x0C, blob->data.length); + memcpy(buffer->data+ofs+0x10, blob->tag, tag_length); + SIVAL(buffer->data, ofs+0x10+tag_length, 0); /* pad? */ + memcpy(buffer->data+ofs+0x14+tag_length, blob->data.data, blob->data.length); + memset(buffer->data+ofs+0x14+tag_length+blob->data.length, 0, pad); + + return NT_STATUS_OK; +} + +NTSTATUS smb2_create_blob_add(TALLOC_CTX *mem_ctx, struct smb2_create_blobs *b, + const char *tag, DATA_BLOB data) +{ + struct smb2_create_blob *array; + + array = talloc_realloc(mem_ctx, b->blobs, + struct smb2_create_blob, + b->num_blobs + 1); + NT_STATUS_HAVE_NO_MEMORY(array); + b->blobs = array; + + b->blobs[b->num_blobs].tag = talloc_strdup(b->blobs, tag); + NT_STATUS_HAVE_NO_MEMORY(b->blobs[b->num_blobs].tag); + + if (data.data) { + b->blobs[b->num_blobs].data = data_blob_talloc(b->blobs, + data.data, + data.length); + NT_STATUS_HAVE_NO_MEMORY(b->blobs[b->num_blobs].data.data); + } else { + b->blobs[b->num_blobs].data = data_blob(NULL, 0); + } + + b->num_blobs += 1; return NT_STATUS_OK; } @@ -64,6 +93,7 @@ struct smb2_request *smb2_create_send(struct smb2_tree *tree, struct smb2_create struct smb2_request *req; NTSTATUS status; DATA_BLOB blob = data_blob(NULL, 0); + uint32_t i; req = smb2_request_init_tree(tree, SMB2_OP_CREATE, 0x38, true, 0); if (req == NULL) return NULL; @@ -89,7 +119,8 @@ 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, SMB2_CREATE_TAG_EXTA, b, false); + status = smb2_create_blob_add(req, &io->in.blobs, + SMB2_CREATE_TAG_EXTA, b); if (!NT_STATUS_IS_OK(status)) { talloc_free(req); return NULL; @@ -99,13 +130,30 @@ 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, SMB2_CREATE_TAG_MXAC, - data_blob(NULL, 0), true); - + status = smb2_create_blob_add(req, &io->in.blobs, + SMB2_CREATE_TAG_MXAC, data_blob(NULL, 0)); if (!NT_STATUS_IS_OK(status)) { talloc_free(req); return NULL; } + + for (i=0; i < io->in.blobs.num_blobs; i++) { + bool last = false; + const struct smb2_create_blob *c; + + if ((i + 1) == io->in.blobs.num_blobs) { + last = true; + } + + c = &io->in.blobs.blobs[i]; + status = smb2_create_blob_push_one(req, &blob, + c, last); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(req); + return NULL; + } + } + status = smb2_push_o32s32_blob(&req->out, 0x30, blob); if (!NT_STATUS_IS_OK(status)) { talloc_free(req); -- cgit From 11703b298685c9984a6a3c3a64eddb8a1a516b90 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 17 Apr 2008 15:20:39 +0200 Subject: fix the overflow/wrap checks in Samba4 for new gcc optimisation behavior The approach I have used is as set out in https://www.securecoding.cert.org/confluence/display/seccode/ARR38-C.+Do+not+add+or+subtract+an+integer+to+a+pointer+if+the+resulting+value+does+not+refer+to+an+element+within+the+array (This used to be commit 92d5fb531db39be655f0cbd2d75b5f675a0a4cfa) --- source4/libcli/smb2/request.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source4/libcli/smb2') diff --git a/source4/libcli/smb2/request.c b/source4/libcli/smb2/request.c index 2471fcaa4d..f52b0ceef2 100644 --- a/source4/libcli/smb2/request.c +++ b/source4/libcli/smb2/request.c @@ -211,10 +211,10 @@ bool smb2_oob(struct smb2_request_buffer *buf, const uint8_t *ptr, size_t size) return false; } /* be careful with wraparound! */ - if (ptr < buf->body || - ptr >= buf->body + buf->body_size || + if ((uintptr_t)ptr < (uintptr_t)buf->body || + (uintptr_t)ptr >= (uintptr_t)buf->body + buf->body_size || size > buf->body_size || - ptr + size > buf->body + buf->body_size) { + (uintptr_t)ptr + size > (uintptr_t)buf->body + buf->body_size) { return true; } return false; @@ -669,7 +669,7 @@ NTSTATUS smb2_push_o16s16_string(struct smb2_request_buffer *buf, } if (*str == 0) { - blob.data = str; + blob.data = discard_const(str); blob.length = 0; return smb2_push_o16s16_blob(buf, ofs, blob); } -- cgit From 0f4a60ff24b2bdb7e2bd73e787613264ec73265c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 18 Apr 2008 22:24:21 +0200 Subject: libcli/smb2: add smb2_break() calls metze (This used to be commit 7f545dbbf0186fe552e4c49a3f618862cb4771e7) --- source4/libcli/smb2/break.c | 74 +++++++++++++++++++++++++++++++++++++++++++ source4/libcli/smb2/config.mk | 2 +- 2 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 source4/libcli/smb2/break.c (limited to 'source4/libcli/smb2') diff --git a/source4/libcli/smb2/break.c b/source4/libcli/smb2/break.c new file mode 100644 index 0000000000..fe0cceb829 --- /dev/null +++ b/source4/libcli/smb2/break.c @@ -0,0 +1,74 @@ +/* + Unix SMB/CIFS implementation. + + SMB2 client oplock break handling + + Copyright (C) Stefan Metzmacher 2008 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "libcli/smb2/smb2.h" +#include "libcli/smb2/smb2_calls.h" + +/* + send a break request +*/ +struct smb2_request *smb2_break_send(struct smb2_tree *tree, struct smb2_break *io) +{ + struct smb2_request *req; + + req = smb2_request_init_tree(tree, SMB2_OP_BREAK, 0x18, false, 0); + if (req == NULL) return NULL; + + SCVAL(req->out.body, 0x02, io->in.oplock_level); + SCVAL(req->out.body, 0x03, io->in.reserved); + SIVAL(req->out.body, 0x04, io->in.reserved2); + smb2_push_handle(req->out.body+0x08, &io->in.file.handle); + + smb2_transport_send(req); + + return req; +} + + +/* + recv a break reply +*/ +NTSTATUS smb2_break_recv(struct smb2_request *req, struct smb2_break *io) +{ + if (!smb2_request_receive(req) || + !smb2_request_is_ok(req)) { + return smb2_request_destroy(req); + } + + SMB2_CHECK_PACKET_RECV(req, 0x18, false); + + io->out.oplock_level = CVAL(req->in.body, 0x02); + io->out.reserved = CVAL(req->in.body, 0x03); + io->out.reserved2 = IVAL(req->in.body, 0x04); + smb2_pull_handle(req->in.body+0x08, &io->out.file.handle); + + return smb2_request_destroy(req); +} + +/* + sync flush request +*/ +NTSTATUS smb2_break(struct smb2_tree *tree, struct smb2_break *io) +{ + struct smb2_request *req = smb2_break_send(tree, io); + return smb2_break_recv(req, io); +} diff --git a/source4/libcli/smb2/config.mk b/source4/libcli/smb2/config.mk index e95997db54..18f6245a3e 100644 --- a/source4/libcli/smb2/config.mk +++ b/source4/libcli/smb2/config.mk @@ -6,5 +6,5 @@ LIBCLI_SMB2_OBJ_FILES = $(addprefix libcli/smb2/, \ transport.o request.o negprot.o session.o tcon.o \ create.o close.o connect.o getinfo.o write.o read.o \ setinfo.o find.o ioctl.o logoff.o tdis.o flush.o \ - lock.o notify.o cancel.o keepalive.o) + lock.o notify.o cancel.o keepalive.o break.o) -- cgit From 132852f44ac24824d2247d3d873f217c5b8207a9 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 18 Apr 2008 22:27:24 +0200 Subject: libcli/smb2: make it possible to handle incoming oplock requests metze (This used to be commit 58189b87eade62b717c2c17c679e482786bf2098) --- source4/libcli/smb2/smb2.h | 11 +++++++++++ source4/libcli/smb2/transport.c | 43 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) (limited to 'source4/libcli/smb2') diff --git a/source4/libcli/smb2/smb2.h b/source4/libcli/smb2/smb2.h index 726df64090..ae66a6e0d3 100644 --- a/source4/libcli/smb2/smb2.h +++ b/source4/libcli/smb2/smb2.h @@ -21,6 +21,8 @@ #include "libcli/raw/request.h" +struct smb2_handle; + struct smb2_options { uint32_t timeout; }; @@ -58,6 +60,15 @@ struct smb2_transport { void *private; uint_t period; } idle; + + struct { + /* a oplock break request handler */ + bool (*handler)(struct smb2_transport *transport, + const struct smb2_handle *handle, + uint8_t level, void *private_data); + /* private data passed to the oplock handler */ + void *private_data; + } oplock; }; diff --git a/source4/libcli/smb2/transport.c b/source4/libcli/smb2/transport.c index af19fcb0a9..8eb60a06f1 100644 --- a/source4/libcli/smb2/transport.c +++ b/source4/libcli/smb2/transport.c @@ -140,6 +140,44 @@ void smb2_transport_dead(struct smb2_transport *transport, NTSTATUS status) } } +static bool smb2_handle_oplock_break(struct smb2_transport *transport, + const DATA_BLOB *blob) +{ + uint8_t *hdr; + uint16_t opcode; + uint64_t seqnum; + + hdr = blob->data+NBT_HDR_SIZE; + + if (blob->length < (SMB2_MIN_SIZE+0x18)) { + DEBUG(1,("Discarding smb2 oplock reply of size %u\n", + blob->length)); + return false; + } + + opcode = SVAL(hdr, SMB2_HDR_OPCODE); + seqnum = BVAL(hdr, SMB2_HDR_MESSAGE_ID); + + if ((opcode != SMB2_OP_BREAK) || + (seqnum != UINT64_MAX)) { + return false; + } + + if (transport->oplock.handler) { + uint8_t *body = hdr+SMB2_HDR_BODY; + struct smb2_handle h; + uint8_t level; + + level = CVAL(body, 0x02); + smb2_pull_handle(body+0x08, &h); + + transport->oplock.handler(transport, &h, level, + transport->oplock.private_data); + } + + return true; +} + /* we have a full request in our receive buffer - match it to a pending request and process @@ -167,6 +205,11 @@ static NTSTATUS smb2_transport_finish_recv(void *private, DATA_BLOB blob) goto error; } + if (smb2_handle_oplock_break(transport, &blob)) { + talloc_free(buffer); + return NT_STATUS_OK; + } + flags = IVAL(hdr, SMB2_HDR_FLAGS); seqnum = BVAL(hdr, SMB2_HDR_MESSAGE_ID); -- cgit From 8846981807a08e86c19b585be135b738eb9edf61 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 15 May 2008 20:46:10 +1000 Subject: update some SMB2 find flags (This used to be commit b7560afd4bab984c0083e9687b69bc42970ad932) --- source4/libcli/smb2/find.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/libcli/smb2') diff --git a/source4/libcli/smb2/find.c b/source4/libcli/smb2/find.c index 6b4902a026..8ebfd81bcd 100644 --- a/source4/libcli/smb2/find.c +++ b/source4/libcli/smb2/find.c @@ -38,7 +38,7 @@ struct smb2_request *smb2_find_send(struct smb2_tree *tree, struct smb2_find *io SCVAL(req->out.body, 0x02, io->in.level); SCVAL(req->out.body, 0x03, io->in.continue_flags); - SIVAL(req->out.body, 0x04, io->in.unknown); + SIVAL(req->out.body, 0x04, io->in.file_index); smb2_push_handle(req->out.body+0x08, &io->in.file.handle); status = smb2_push_o16s16_string(&req->out, 0x18, io->in.pattern); -- cgit From c7d7577fb978dfa822b4aab238440816188099c6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 16 May 2008 15:03:58 +1000 Subject: private -> private_data for struct smb2_request (This used to be commit 67290e0ad69df2f2fe651249c6550b8e32dd641b) --- source4/libcli/smb2/connect.c | 8 ++++---- source4/libcli/smb2/request.c | 25 +++++++++++++++++-------- source4/libcli/smb2/session.c | 4 ++-- source4/libcli/smb2/smb2.h | 7 ++++++- 4 files changed, 29 insertions(+), 15 deletions(-) (limited to 'source4/libcli/smb2') diff --git a/source4/libcli/smb2/connect.c b/source4/libcli/smb2/connect.c index 59d4e6ea2d..867af14c92 100644 --- a/source4/libcli/smb2/connect.c +++ b/source4/libcli/smb2/connect.c @@ -44,7 +44,7 @@ struct smb2_connect_state { */ static void continue_tcon(struct smb2_request *req) { - struct composite_context *c = talloc_get_type(req->async.private, + struct composite_context *c = talloc_get_type(req->async.private_data, struct composite_context); struct smb2_connect_state *state = talloc_get_type(c->private_data, struct smb2_connect_state); @@ -83,7 +83,7 @@ static void continue_session(struct composite_context *creq) if (composite_nomem(req, c)) return; req->async.fn = continue_tcon; - req->async.private = c; + req->async.private_data = c; } /* @@ -91,7 +91,7 @@ static void continue_session(struct composite_context *creq) */ static void continue_negprot(struct smb2_request *req) { - struct composite_context *c = talloc_get_type(req->async.private, + struct composite_context *c = talloc_get_type(req->async.private_data, struct composite_context); struct smb2_connect_state *state = talloc_get_type(c->private_data, struct smb2_connect_state); @@ -142,7 +142,7 @@ static void continue_socket(struct composite_context *creq) if (composite_nomem(req, c)) return; req->async.fn = continue_negprot; - req->async.private = c; + req->async.private_data = c; } diff --git a/source4/libcli/smb2/request.c b/source4/libcli/smb2/request.c index f52b0ceef2..64d427f889 100644 --- a/source4/libcli/smb2/request.c +++ b/source4/libcli/smb2/request.c @@ -43,6 +43,18 @@ void smb2_setup_bufinfo(struct smb2_request *req) } } + +/* destroy a request structure */ +static int smb2_request_destructor(struct smb2_request *req) +{ + if (req->transport) { + /* remove it from the list of pending requests (a null op if + its not in the list) */ + DLIST_REMOVE(req->transport->pending_recv, req); + } + return 0; +} + /* initialise a smb2 request */ @@ -122,6 +134,8 @@ struct smb2_request *smb2_request_init(struct smb2_transport *transport, uint16_ SCVAL(req->out.dynamic, 0, 0); } + talloc_set_destructor(req, smb2_request_destructor); + return req; } @@ -154,18 +168,13 @@ NTSTATUS smb2_request_destroy(struct smb2_request *req) _send() call fails completely */ if (!req) return NT_STATUS_UNSUCCESSFUL; - if (req->transport) { - /* remove it from the list of pending requests (a null op if - its not in the list) */ - DLIST_REMOVE(req->transport->pending_recv, req); - } - if (req->state == SMB2_REQUEST_ERROR && NT_STATUS_IS_OK(req->status)) { - req->status = NT_STATUS_INTERNAL_ERROR; + status = NT_STATUS_INTERNAL_ERROR; + } else { + status = req->status; } - status = req->status; talloc_free(req); return status; } diff --git a/source4/libcli/smb2/session.c b/source4/libcli/smb2/session.c index 18fe3486a4..29af6652f2 100644 --- a/source4/libcli/smb2/session.c +++ b/source4/libcli/smb2/session.c @@ -145,7 +145,7 @@ struct smb2_session_state { */ static void session_request_handler(struct smb2_request *req) { - struct composite_context *c = talloc_get_type(req->async.private, + struct composite_context *c = talloc_get_type(req->async.private_data, struct composite_context); struct smb2_session_state *state = talloc_get_type(c->private_data, struct smb2_session_state); @@ -178,7 +178,7 @@ static void session_request_handler(struct smb2_request *req) } state->req->async.fn = session_request_handler; - state->req->async.private = c; + state->req->async.private_data = c; return; } diff --git a/source4/libcli/smb2/smb2.h b/source4/libcli/smb2/smb2.h index ae66a6e0d3..964dcf320c 100644 --- a/source4/libcli/smb2/smb2.h +++ b/source4/libcli/smb2/smb2.h @@ -19,6 +19,9 @@ along with this program. If not, see . */ +#ifndef __LIBCLI_SMB2_SMB2_H__ +#define __LIBCLI_SMB2_SMB2_H__ + #include "libcli/raw/request.h" struct smb2_handle; @@ -165,7 +168,7 @@ struct smb2_request { */ struct { void (*fn)(struct smb2_request *); - void *private; + void *private_data; } async; }; @@ -282,3 +285,5 @@ struct smb2_request { return NT_STATUS_INVALID_PARAMETER; \ } \ } while (0) + +#endif -- cgit From 03643aec88244d976da394521adbd29a31339569 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 18 May 2008 19:54:27 +0200 Subject: Use variables for source directory in a couple more places. (This used to be commit c41bd3005f5f0b9cfd3709fc9217b4a401d265b4) --- source4/libcli/smb2/config.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/libcli/smb2') diff --git a/source4/libcli/smb2/config.mk b/source4/libcli/smb2/config.mk index 18f6245a3e..d00ef6e03b 100644 --- a/source4/libcli/smb2/config.mk +++ b/source4/libcli/smb2/config.mk @@ -2,7 +2,7 @@ PRIVATE_PROTO_HEADER = smb2_proto.h PUBLIC_DEPENDENCIES = LIBCLI_RAW LIBPACKET gensec -LIBCLI_SMB2_OBJ_FILES = $(addprefix libcli/smb2/, \ +LIBCLI_SMB2_OBJ_FILES = $(addprefix $(libclisrcdir)/smb2/, \ transport.o request.o negprot.o session.o tcon.o \ create.o close.o connect.o getinfo.o write.o read.o \ setinfo.o find.o ioctl.o logoff.o tdis.o flush.o \ -- cgit From 4c8756f147f8b9a2806fd76e4cb06bb99d391516 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 18 May 2008 22:30:08 +0200 Subject: Create prototype headers from Makefile directory, without smb_build in the middle. (This used to be commit f4a77b96f9c17d853348b70794026e5b9e384942) --- source4/libcli/smb2/config.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/libcli/smb2') diff --git a/source4/libcli/smb2/config.mk b/source4/libcli/smb2/config.mk index d00ef6e03b..1d0126dca8 100644 --- a/source4/libcli/smb2/config.mk +++ b/source4/libcli/smb2/config.mk @@ -1,5 +1,4 @@ [SUBSYSTEM::LIBCLI_SMB2] -PRIVATE_PROTO_HEADER = smb2_proto.h PUBLIC_DEPENDENCIES = LIBCLI_RAW LIBPACKET gensec LIBCLI_SMB2_OBJ_FILES = $(addprefix $(libclisrcdir)/smb2/, \ @@ -8,3 +7,4 @@ LIBCLI_SMB2_OBJ_FILES = $(addprefix $(libclisrcdir)/smb2/, \ setinfo.o find.o ioctl.o logoff.o tdis.o flush.o \ lock.o notify.o cancel.o keepalive.o break.o) +$(call proto_header_template,$(libclisrcdir)/smb2_proto.h,$(LIBCLI_SMB2_OBJ_FILES:.o=.c)) -- cgit From 4c70cda986c86fe536327321d04c29eca81b6409 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 18 May 2008 23:02:47 +0200 Subject: Fix a couple (well, little more than that..) of typos. (This used to be commit a6b52119940a900fb0de3864b8bca94e2965cc24) --- source4/libcli/smb2/config.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/libcli/smb2') diff --git a/source4/libcli/smb2/config.mk b/source4/libcli/smb2/config.mk index 1d0126dca8..ea41d5924e 100644 --- a/source4/libcli/smb2/config.mk +++ b/source4/libcli/smb2/config.mk @@ -7,4 +7,4 @@ LIBCLI_SMB2_OBJ_FILES = $(addprefix $(libclisrcdir)/smb2/, \ setinfo.o find.o ioctl.o logoff.o tdis.o flush.o \ lock.o notify.o cancel.o keepalive.o break.o) -$(call proto_header_template,$(libclisrcdir)/smb2_proto.h,$(LIBCLI_SMB2_OBJ_FILES:.o=.c)) +$(eval $(call proto_header_template,$(libclisrcdir)/smb2_proto.h,$(LIBCLI_SMB2_OBJ_FILES:.o=.c))) -- cgit From 60ae8f06574c74261643f469e6be2a945fd90880 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 18 May 2008 23:40:23 +0200 Subject: Fix a bunch of dependencies. (This used to be commit a63f458462d207d215a6e4ef8e480b0c8daedf6a) --- source4/libcli/smb2/config.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/libcli/smb2') diff --git a/source4/libcli/smb2/config.mk b/source4/libcli/smb2/config.mk index ea41d5924e..e653fbac1c 100644 --- a/source4/libcli/smb2/config.mk +++ b/source4/libcli/smb2/config.mk @@ -7,4 +7,4 @@ LIBCLI_SMB2_OBJ_FILES = $(addprefix $(libclisrcdir)/smb2/, \ setinfo.o find.o ioctl.o logoff.o tdis.o flush.o \ lock.o notify.o cancel.o keepalive.o break.o) -$(eval $(call proto_header_template,$(libclisrcdir)/smb2_proto.h,$(LIBCLI_SMB2_OBJ_FILES:.o=.c))) +$(eval $(call proto_header_template,$(libclisrcdir)/smb2/smb2_proto.h,$(LIBCLI_SMB2_OBJ_FILES:.o=.c))) -- cgit From 9c6a35ad9ba9458fe9d3a73ba1f785a61305e2aa Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 20 May 2008 11:57:43 +1000 Subject: remember the server time fields on negotiate. Needed for gentest (This used to be commit 7989ca861dcc700b52be3a47ea5ae8b03fbb9330) --- source4/libcli/smb2/connect.c | 3 +++ source4/libcli/smb2/smb2.h | 2 ++ 2 files changed, 5 insertions(+) (limited to 'source4/libcli/smb2') diff --git a/source4/libcli/smb2/connect.c b/source4/libcli/smb2/connect.c index 867af14c92..eabfa410ad 100644 --- a/source4/libcli/smb2/connect.c +++ b/source4/libcli/smb2/connect.c @@ -101,6 +101,9 @@ static void continue_negprot(struct smb2_request *req) c->status = smb2_negprot_recv(req, c, &state->negprot); if (!composite_is_ok(c)) return; + transport->negotiate.system_time = state->negprot.out.system_time; + transport->negotiate.server_start_time = state->negprot.out.server_start_time; + state->session = smb2_session_init(transport, global_loadparm, state, true); if (composite_nomem(state->session, c)) return; diff --git a/source4/libcli/smb2/smb2.h b/source4/libcli/smb2/smb2.h index 964dcf320c..b55da05e21 100644 --- a/source4/libcli/smb2/smb2.h +++ b/source4/libcli/smb2/smb2.h @@ -35,6 +35,8 @@ struct smb2_options { */ struct smb2_negotiate { DATA_BLOB secblob; + NTTIME system_time; + NTTIME server_start_time; }; /* this is the context for the smb2 transport layer */ -- cgit From 803c076450da4075c71faaba3f0882f0b8e6208a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 20 May 2008 11:58:04 +1000 Subject: added some SMB2 utility functions (This used to be commit 6a3b1cd6698faa460c6258bb41b4936e363f4387) --- source4/libcli/smb2/config.mk | 2 +- source4/libcli/smb2/util.c | 178 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 179 insertions(+), 1 deletion(-) create mode 100644 source4/libcli/smb2/util.c (limited to 'source4/libcli/smb2') diff --git a/source4/libcli/smb2/config.mk b/source4/libcli/smb2/config.mk index e653fbac1c..00b6305def 100644 --- a/source4/libcli/smb2/config.mk +++ b/source4/libcli/smb2/config.mk @@ -5,6 +5,6 @@ LIBCLI_SMB2_OBJ_FILES = $(addprefix $(libclisrcdir)/smb2/, \ transport.o request.o negprot.o session.o tcon.o \ create.o close.o connect.o getinfo.o write.o read.o \ setinfo.o find.o ioctl.o logoff.o tdis.o flush.o \ - lock.o notify.o cancel.o keepalive.o break.o) + lock.o notify.o cancel.o keepalive.o break.o util.o) $(eval $(call proto_header_template,$(libclisrcdir)/smb2/smb2_proto.h,$(LIBCLI_SMB2_OBJ_FILES:.o=.c))) diff --git a/source4/libcli/smb2/util.c b/source4/libcli/smb2/util.c new file mode 100644 index 0000000000..0fc03b48c5 --- /dev/null +++ b/source4/libcli/smb2/util.c @@ -0,0 +1,178 @@ +/* + Unix SMB/CIFS implementation. + + SMB2 client utility functions + + Copyright (C) Andrew Tridgell 2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "libcli/raw/libcliraw.h" +#include "libcli/raw/raw_proto.h" +#include "libcli/smb2/smb2.h" +#include "libcli/smb2/smb2_calls.h" +#include "libcli/smb_composite/smb_composite.h" + +/* + simple close wrapper with SMB2 +*/ +NTSTATUS smb2_util_close(struct smb2_tree *tree, struct smb2_handle h) +{ + struct smb2_close c; + + ZERO_STRUCT(c); + c.in.file.handle = h; + + return smb2_close(tree, &c); +} + +/* + unlink a file with SMB2 +*/ +NTSTATUS smb2_util_unlink(struct smb2_tree *tree, const char *fname) +{ + union smb_unlink io; + + ZERO_STRUCT(io); + io.unlink.in.pattern = fname; + + return smb2_composite_unlink(tree, &io); +} + + +/* + rmdir with SMB2 +*/ +NTSTATUS smb2_util_rmdir(struct smb2_tree *tree, const char *dname) +{ + struct smb_rmdir io; + + ZERO_STRUCT(io); + io.in.path = dname; + + return smb2_composite_rmdir(tree, &io); +} + + +/* + mkdir with SMB2 +*/ +NTSTATUS smb2_util_mkdir(struct smb2_tree *tree, const char *dname) +{ + union smb_mkdir io; + + ZERO_STRUCT(io); + io.mkdir.level = RAW_MKDIR_MKDIR; + io.mkdir.in.path = dname; + + return smb2_composite_mkdir(tree, &io); +} + + + + +/* + recursively descend a tree deleting all files + returns the number of files deleted, or -1 on error +*/ +int smb2_deltree(struct smb2_tree *tree, const char *dname) +{ + NTSTATUS status; + uint32_t total_deleted = 0; + uint_t count, i; + union smb_search_data *list; + TALLOC_CTX *tmp_ctx = talloc_new(tree); + struct smb2_find f; + struct smb2_create create_parm; + + /* it might be a file */ + status = smb2_util_unlink(tree, dname); + if (NT_STATUS_IS_OK(status)) { + talloc_free(tmp_ctx); + return 1; + } + if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) || + NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND) || + NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_FILE)) { + talloc_free(tmp_ctx); + return 0; + } + + ZERO_STRUCT(create_parm); + create_parm.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED; + create_parm.in.share_access = + NTCREATEX_SHARE_ACCESS_READ| + NTCREATEX_SHARE_ACCESS_WRITE; + create_parm.in.create_options = NTCREATEX_OPTIONS_DIRECTORY; + create_parm.in.create_disposition = NTCREATEX_DISP_OPEN; + create_parm.in.fname = dname; + + status = smb2_create(tree, tmp_ctx, &create_parm); + if (NT_STATUS_IS_ERR(status)) { + DEBUG(2,("Failed to open %s - %s\n", dname, nt_errstr(status))); + talloc_free(tmp_ctx); + return -1; + } + + + ZERO_STRUCT(f); + f.in.file.handle = create_parm.out.file.handle; + f.in.max_response_size = 0x10000; + f.in.level = SMB2_FIND_NAME_INFO; + f.in.pattern = "*"; + + status = smb2_find_level(tree, tmp_ctx, &f, &count, &list); + if (NT_STATUS_IS_ERR(status)) { + DEBUG(2,("Failed to list %s - %s\n", + dname, nt_errstr(status))); + smb2_util_close(tree, create_parm.out.file.handle); + talloc_free(tmp_ctx); + return -1; + } + + for (i=0;i 0) total_deleted += ret; + } + talloc_free(name); + if (NT_STATUS_IS_OK(status)) { + total_deleted++; + } + } + + smb2_util_close(tree, create_parm.out.file.handle); + + status = smb2_util_rmdir(tree, dname); + if (NT_STATUS_IS_ERR(status)) { + DEBUG(2,("Failed to delete %s - %s\n", + dname, nt_errstr(status))); + talloc_free(tmp_ctx); + return -1; + } + + talloc_free(tmp_ctx); + + return total_deleted; +} -- cgit From 2214e6d9bfdc52db0558e831691b4500405ab9ae Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 20 May 2008 13:37:51 +1000 Subject: added smb2_util_setatr (This used to be commit d4f41db964ce82c8889017d0f932d60100b3cd32) --- source4/libcli/smb2/util.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'source4/libcli/smb2') diff --git a/source4/libcli/smb2/util.c b/source4/libcli/smb2/util.c index 0fc03b48c5..9eb344e83f 100644 --- a/source4/libcli/smb2/util.c +++ b/source4/libcli/smb2/util.c @@ -82,6 +82,22 @@ NTSTATUS smb2_util_mkdir(struct smb2_tree *tree, const char *dname) } +/* + set file attribute with SMB2 +*/ +NTSTATUS smb2_util_setatr(struct smb2_tree *tree, const char *name, uint32_t attrib) +{ + union smb_setfileinfo io; + + ZERO_STRUCT(io); + io.basic_info.level = RAW_SFILEINFO_BASIC_INFORMATION; + io.basic_info.in.file.path = name; + io.basic_info.in.attrib = attrib; + + return smb2_composite_setpathinfo(tree, &io); +} + + /* @@ -151,6 +167,12 @@ int smb2_deltree(struct smb2_tree *tree, const char *dname) } name = talloc_asprintf(tmp_ctx, "%s\\%s", dname, list[i].name_info.name.s); status = smb2_util_unlink(tree, name); + if (NT_STATUS_EQUAL(status, NT_STATUS_CANNOT_DELETE)) { + /* it could be read-only */ + status = smb2_util_setatr(tree, name, FILE_ATTRIBUTE_NORMAL); + status = smb2_util_unlink(tree, name); + } + if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) { int ret; ret = smb2_deltree(tree, name); -- cgit From 4d39976dddf2adf6a0d659050c3a21a6e0ff8ab2 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 21 May 2008 22:12:20 +1000 Subject: fixed SMB2 locking - SMB2 locking is different in several ways from SMB locking. To fix it properly we will need a new generic mapping structure for locking, but for now do a best effort mapping - added locking to gentest_smb2 (This used to be commit ea6d9cf602302adafe0f9d5f5f90a9b26d1ead6f) --- source4/libcli/smb2/lock.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) (limited to 'source4/libcli/smb2') diff --git a/source4/libcli/smb2/lock.c b/source4/libcli/smb2/lock.c index d71a337d56..62c6e5dba7 100644 --- a/source4/libcli/smb2/lock.c +++ b/source4/libcli/smb2/lock.c @@ -29,17 +29,25 @@ struct smb2_request *smb2_lock_send(struct smb2_tree *tree, struct smb2_lock *io) { struct smb2_request *req; + int i; - req = smb2_request_init_tree(tree, SMB2_OP_LOCK, 0x30, false, 0); + req = smb2_request_init_tree(tree, SMB2_OP_LOCK, + 24 + io->in.lock_count*24, false, 0); if (req == NULL) return NULL; - SSVAL(req->out.body, 0x02, io->in.unknown1); - SIVAL(req->out.body, 0x04, io->in.unknown2); + /* this is quite bizarre - the spec says we must lie about the length! */ + SSVAL(req->out.body, 0, 0x30); + + SSVAL(req->out.body, 0x02, io->in.lock_count); + SIVAL(req->out.body, 0x04, io->in.reserved); smb2_push_handle(req->out.body+0x08, &io->in.file.handle); - SBVAL(req->out.body, 0x18, io->in.offset); - SBVAL(req->out.body, 0x20, io->in.count); - SIVAL(req->out.body, 0x24, io->in.unknown5); - SIVAL(req->out.body, 0x28, io->in.flags); + + for (i=0;iin.lock_count;i++) { + SBVAL(req->out.body, 0x18 + i*24, io->in.locks[i].offset); + SBVAL(req->out.body, 0x20 + i*24, io->in.locks[i].length); + SIVAL(req->out.body, 0x28 + i*24, io->in.locks[i].flags); + SIVAL(req->out.body, 0x2C + i*24, io->in.locks[i].reserved); + } smb2_transport_send(req); @@ -59,7 +67,7 @@ NTSTATUS smb2_lock_recv(struct smb2_request *req, struct smb2_lock *io) SMB2_CHECK_PACKET_RECV(req, 0x04, false); - io->out.unknown1 = SVAL(req->in.body, 0x02); + io->out.reserved = SVAL(req->in.body, 0x02); return smb2_request_destroy(req); } -- cgit From aed93a238e13247945073921d91408c91ae210c3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 21 May 2008 22:51:21 +1000 Subject: fixed SMB2 flush call, and added flush to gentest_smb2 (This used to be commit c52fe1fe1c77636d87355d3c4baa66e052fe9008) --- source4/libcli/smb2/flush.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source4/libcli/smb2') diff --git a/source4/libcli/smb2/flush.c b/source4/libcli/smb2/flush.c index 116068ed6e..577d1ba1ba 100644 --- a/source4/libcli/smb2/flush.c +++ b/source4/libcli/smb2/flush.c @@ -33,8 +33,8 @@ struct smb2_request *smb2_flush_send(struct smb2_tree *tree, struct smb2_flush * req = smb2_request_init_tree(tree, SMB2_OP_FLUSH, 0x18, false, 0); if (req == NULL) return NULL; - SSVAL(req->out.body, 0x02, 0); /* pad? */ - SIVAL(req->out.body, 0x04, io->in.unknown); + SSVAL(req->out.body, 0x02, io->in.reserved1); + SIVAL(req->out.body, 0x04, io->in.reserved2); smb2_push_handle(req->out.body+0x08, &io->in.file.handle); smb2_transport_send(req); @@ -55,6 +55,8 @@ NTSTATUS smb2_flush_recv(struct smb2_request *req, struct smb2_flush *io) SMB2_CHECK_PACKET_RECV(req, 0x04, false); + io->out.reserved = SVAL(req->in.body, 0x02); + return smb2_request_destroy(req); } -- cgit From d5def936fe67c1cde2c4ed00834c4ce325dfcb55 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 22 May 2008 22:46:29 +1000 Subject: pass in the required alignment to the EA construction routines (This used to be commit af31030e0b78b6b220740529901ec8d2d9f5a3fe) --- source4/libcli/smb2/create.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/libcli/smb2') diff --git a/source4/libcli/smb2/create.c b/source4/libcli/smb2/create.c index 6ac32a494f..9d28bbf8c4 100644 --- a/source4/libcli/smb2/create.c +++ b/source4/libcli/smb2/create.c @@ -117,8 +117,8 @@ struct smb2_request *smb2_create_send(struct smb2_tree *tree, struct smb2_create if (io->in.eas.num_eas != 0) { 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); + ea_list_size_chained(io->in.eas.num_eas, io->in.eas.eas, 8)); + ea_put_list_chained(b.data, io->in.eas.num_eas, io->in.eas.eas, 8); status = smb2_create_blob_add(req, &io->in.blobs, SMB2_CREATE_TAG_EXTA, b); if (!NT_STATUS_IS_OK(status)) { -- cgit From ec7a6ee8ab25f4550a68b286d9eba32b955a73a1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 23 May 2008 00:07:12 +1000 Subject: fix make test for EAs again - go back to 4 byte alignment until I work out the rules that Vista wants more exactly - add the zero sized EA handling for SMB2 more generically (This used to be commit 326b69bc8064cbea357864cecd6bd27b50c57184) --- source4/libcli/smb2/create.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/libcli/smb2') diff --git a/source4/libcli/smb2/create.c b/source4/libcli/smb2/create.c index 9d28bbf8c4..b1b8b0ccfa 100644 --- a/source4/libcli/smb2/create.c +++ b/source4/libcli/smb2/create.c @@ -117,8 +117,8 @@ struct smb2_request *smb2_create_send(struct smb2_tree *tree, struct smb2_create if (io->in.eas.num_eas != 0) { DATA_BLOB b = data_blob_talloc(req, NULL, - ea_list_size_chained(io->in.eas.num_eas, io->in.eas.eas, 8)); - ea_put_list_chained(b.data, io->in.eas.num_eas, io->in.eas.eas, 8); + ea_list_size_chained(io->in.eas.num_eas, io->in.eas.eas, 4)); + ea_put_list_chained(b.data, io->in.eas.num_eas, io->in.eas.eas, 4); status = smb2_create_blob_add(req, &io->in.blobs, SMB2_CREATE_TAG_EXTA, b); if (!NT_STATUS_IS_OK(status)) { -- cgit