summaryrefslogtreecommitdiff
path: root/source3/libsmb
diff options
context:
space:
mode:
Diffstat (limited to 'source3/libsmb')
-rw-r--r--source3/libsmb/async_smb.c483
-rw-r--r--source3/libsmb/cliconnect.c27
-rw-r--r--source3/libsmb/clientgen.c120
-rw-r--r--source3/libsmb/clierror.c12
-rw-r--r--source3/libsmb/clifile.c58
-rw-r--r--source3/libsmb/clifsinfo.c11
-rw-r--r--source3/libsmb/clikrb5.c14
-rw-r--r--source3/libsmb/clilist.c68
-rw-r--r--source3/libsmb/clirap.c138
-rw-r--r--source3/libsmb/clireadwrite.c510
-rw-r--r--source3/libsmb/clispnego.c6
-rw-r--r--source3/libsmb/credentials.c92
-rw-r--r--source3/libsmb/doserr.c11
-rw-r--r--source3/libsmb/dsgetdcname.c256
-rw-r--r--source3/libsmb/libsmb_compat.c6
-rw-r--r--source3/libsmb/libsmbclient.c177
-rw-r--r--source3/libsmb/namequery.c10
-rw-r--r--source3/libsmb/ntlmssp_parse.c23
-rw-r--r--source3/libsmb/samlogon_cache.c220
-rw-r--r--source3/libsmb/smb_seal.c6
-rw-r--r--source3/libsmb/smb_signing.c8
-rw-r--r--source3/libsmb/trusts_util.c59
22 files changed, 1745 insertions, 570 deletions
diff --git a/source3/libsmb/async_smb.c b/source3/libsmb/async_smb.c
new file mode 100644
index 0000000000..21bcd5b9b1
--- /dev/null
+++ b/source3/libsmb/async_smb.c
@@ -0,0 +1,483 @@
+/*
+ Unix SMB/CIFS implementation.
+ Infrastructure for async SMB client requests
+ Copyright (C) Volker Lendecke 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 <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+
+/*
+ * Fetch an error out of a NBT packet
+ */
+
+NTSTATUS cli_pull_error(char *buf)
+{
+ uint32_t flags2 = SVAL(buf, smb_flg2);
+
+ if (flags2 & FLAGS2_32_BIT_ERROR_CODES) {
+ return NT_STATUS(IVAL(buf, smb_rcls));
+ }
+
+ return NT_STATUS_DOS(CVAL(buf, smb_rcls), SVAL(buf,smb_err));
+}
+
+/*
+ * Compatibility helper for the sync APIs: Fake NTSTATUS in cli->inbuf
+ */
+
+void cli_set_error(struct cli_state *cli, NTSTATUS status)
+{
+ uint32_t flags2 = SVAL(cli->inbuf, smb_flg2);
+
+ if (NT_STATUS_IS_DOS(status)) {
+ SSVAL(cli->inbuf, smb_flg2,
+ flags2 & ~FLAGS2_32_BIT_ERROR_CODES);
+ SCVAL(cli->inbuf, smb_rcls, NT_STATUS_DOS_CLASS(status));
+ SSVAL(cli->inbuf, smb_err, NT_STATUS_DOS_CODE(status));
+ return;
+ }
+
+ SSVAL(cli->inbuf, smb_flg2, flags2 | FLAGS2_32_BIT_ERROR_CODES);
+ SIVAL(cli->inbuf, smb_rcls, NT_STATUS_V(status));
+ return;
+}
+
+/*
+ * Allocate a new mid
+ */
+
+static uint16_t cli_new_mid(struct cli_state *cli)
+{
+ uint16_t result;
+ struct cli_request *req;
+
+ while (true) {
+ result = cli->mid++;
+ if (result == 0) {
+ continue;
+ }
+
+ for (req = cli->outstanding_requests; req; req = req->next) {
+ if (result == req->mid) {
+ break;
+ }
+ }
+
+ if (req == NULL) {
+ return result;
+ }
+ }
+}
+
+static char *cli_request_print(TALLOC_CTX *mem_ctx, struct async_req *req)
+{
+ char *result = async_req_print(mem_ctx, req);
+ struct cli_request *cli_req = cli_request_get(req);
+
+ if (result == NULL) {
+ return NULL;
+ }
+
+ return talloc_asprintf_append_buffer(
+ result, "mid=%d\n", cli_req->mid);
+}
+
+static int cli_request_destructor(struct cli_request *req)
+{
+ if (req->enc_state != NULL) {
+ common_free_enc_buffer(req->enc_state, req->outbuf);
+ }
+ DLIST_REMOVE(req->cli->outstanding_requests, req);
+ return 0;
+}
+
+/*
+ * Create a fresh async smb request
+ */
+
+struct async_req *cli_request_new(TALLOC_CTX *mem_ctx,
+ struct event_context *ev,
+ struct cli_state *cli,
+ uint8_t num_words, size_t num_bytes,
+ struct cli_request **preq)
+{
+ struct async_req *result;
+ struct cli_request *cli_req;
+ size_t bufsize = smb_size + num_words * 2 + num_bytes;
+
+ result = async_req_new(mem_ctx, ev);
+ if (result == NULL) {
+ return NULL;
+ }
+
+ cli_req = (struct cli_request *)talloc_size(
+ result, sizeof(*cli_req) + bufsize);
+ if (cli_req == NULL) {
+ TALLOC_FREE(result);
+ return NULL;
+ }
+ talloc_set_name_const(cli_req, "struct cli_request");
+ result->private_data = cli_req;
+ result->print = cli_request_print;
+
+ cli_req->async = result;
+ cli_req->cli = cli;
+ cli_req->outbuf = ((char *)cli_req + sizeof(*cli_req));
+ cli_req->sent = 0;
+ cli_req->mid = cli_new_mid(cli);
+ cli_req->inbuf = NULL;
+ cli_req->enc_state = NULL;
+
+ SCVAL(cli_req->outbuf, smb_wct, num_words);
+ SSVAL(cli_req->outbuf, smb_vwv + num_words * 2, num_bytes);
+
+ DLIST_ADD_END(cli->outstanding_requests, cli_req,
+ struct cli_request *);
+ talloc_set_destructor(cli_req, cli_request_destructor);
+
+ DEBUG(10, ("cli_request_new: mid=%d\n", cli_req->mid));
+
+ *preq = cli_req;
+ return result;
+}
+
+/*
+ * Convenience function to get the SMB part out of an async_req
+ */
+
+struct cli_request *cli_request_get(struct async_req *req)
+{
+ if (req == NULL) {
+ return NULL;
+ }
+ return talloc_get_type_abort(req->private_data, struct cli_request);
+}
+
+/*
+ * A PDU has arrived on cli->evt_inbuf
+ */
+
+static void handle_incoming_pdu(struct cli_state *cli)
+{
+ struct cli_request *req;
+ uint16_t mid;
+ size_t raw_pdu_len, buf_len, pdu_len;
+ size_t rest_len;
+ NTSTATUS status;
+
+ /*
+ * The encrypted PDU len might differ from the unencrypted one
+ */
+ raw_pdu_len = smb_len(cli->evt_inbuf) + 4;
+
+ /*
+ * TODO: Handle oplock break requests
+ */
+
+ if (cli_encryption_on(cli) && CVAL(cli->evt_inbuf, 0) == 0) {
+ uint16_t enc_ctx_num;
+
+ status = get_enc_ctx_num((uint8_t *)cli->evt_inbuf,
+ &enc_ctx_num);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10, ("get_enc_ctx_num returned %s\n",
+ nt_errstr(status)));
+ goto invalidate_requests;
+ }
+
+ if (enc_ctx_num != cli->trans_enc_state->enc_ctx_num) {
+ DEBUG(10, ("wrong enc_ctx %d, expected %d\n",
+ enc_ctx_num,
+ cli->trans_enc_state->enc_ctx_num));
+ status = NT_STATUS_INVALID_HANDLE;
+ goto invalidate_requests;
+ }
+
+ status = common_decrypt_buffer(cli->trans_enc_state,
+ cli->evt_inbuf);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10, ("common_decrypt_buffer returned %s\n",
+ nt_errstr(status)));
+ goto invalidate_requests;
+ }
+ }
+
+ if (!cli_check_sign_mac(cli, cli->evt_inbuf)) {
+ DEBUG(10, ("cli_check_sign_mac failed\n"));
+ status = NT_STATUS_ACCESS_DENIED;
+ goto invalidate_requests;
+ }
+
+ mid = SVAL(cli->evt_inbuf, smb_mid);
+
+ DEBUG(10, ("handle_incoming_pdu: got mid %d\n", mid));
+
+ for (req = cli->outstanding_requests; req; req = req->next) {
+ if (req->mid == mid) {
+ break;
+ }
+ }
+
+ buf_len = talloc_get_size(cli->evt_inbuf);
+ pdu_len = smb_len(cli->evt_inbuf) + 4;
+ rest_len = buf_len - raw_pdu_len;
+
+ if (req == NULL) {
+ DEBUG(3, ("Request for mid %d not found, dumping PDU\n", mid));
+
+ memmove(cli->evt_inbuf, cli->evt_inbuf + raw_pdu_len,
+ buf_len - raw_pdu_len);
+
+ cli->evt_inbuf = TALLOC_REALLOC_ARRAY(NULL, cli->evt_inbuf,
+ char, rest_len);
+ return;
+ }
+
+ if (buf_len == pdu_len) {
+ /*
+ * Optimal case: Exactly one PDU was in the socket buffer
+ */
+ req->inbuf = talloc_move(req, &cli->evt_inbuf);
+ goto done;
+ }
+
+ DEBUG(11, ("buf_len = %d, pdu_len = %d, splitting buffer\n",
+ (int)buf_len, (int)pdu_len));
+
+ if (pdu_len < rest_len) {
+ /*
+ * The PDU is shorter, talloc_memdup that one.
+ */
+ req->inbuf = (char *)talloc_memdup(
+ req, cli->evt_inbuf, pdu_len);
+
+ memmove(cli->evt_inbuf,
+ cli->evt_inbuf + raw_pdu_len,
+ buf_len - raw_pdu_len);
+
+ cli->evt_inbuf = TALLOC_REALLOC_ARRAY(
+ NULL, cli->evt_inbuf, char, rest_len);
+ }
+ else {
+ /*
+ * The PDU is larger than the rest,
+ * talloc_memdup the rest
+ */
+ req->inbuf = talloc_move(req, &cli->evt_inbuf);
+
+ cli->evt_inbuf = (char *)talloc_memdup(
+ cli, req->inbuf + raw_pdu_len,
+ rest_len);
+ }
+
+ if ((req->inbuf == NULL) || (cli->evt_inbuf == NULL)) {
+ status = NT_STATUS_NO_MEMORY;
+ goto invalidate_requests;
+ }
+
+ done:
+ async_req_done(req->async);
+ return;
+
+ invalidate_requests:
+
+ DEBUG(10, ("handle_incoming_pdu: Aborting with %s\n",
+ nt_errstr(status)));
+
+ for (req = cli->outstanding_requests; req; req = req->next) {
+ async_req_error(req->async, status);
+ }
+ return;
+}
+
+/*
+ * fd event callback. This is the basic connection to the socket
+ */
+
+static void cli_state_handler(struct event_context *event_ctx,
+ struct fd_event *event, uint16 flags, void *p)
+{
+ struct cli_state *cli = (struct cli_state *)p;
+ struct cli_request *req;
+
+ DEBUG(11, ("cli_state_handler called with flags %d\n", flags));
+
+ if (flags & EVENT_FD_READ) {
+ int res, available;
+ size_t old_size, new_size;
+ char *tmp;
+
+ res = ioctl(cli->fd, FIONREAD, &available);
+ if (res == -1) {
+ DEBUG(10, ("ioctl(FIONREAD) failed: %s\n",
+ strerror(errno)));
+ goto sock_error;
+ }
+
+ if (available == 0) {
+ /* EOF */
+ goto sock_error;
+ }
+
+ old_size = talloc_get_size(cli->evt_inbuf);
+ new_size = old_size + available;
+
+ if (new_size < old_size) {
+ /* wrap */
+ goto sock_error;
+ }
+
+ tmp = TALLOC_REALLOC_ARRAY(cli, cli->evt_inbuf, char,
+ new_size);
+ if (tmp == NULL) {
+ /* nomem */
+ goto sock_error;
+ }
+ cli->evt_inbuf = tmp;
+
+ res = recv(cli->fd, cli->evt_inbuf + old_size, available, 0);
+ if (res == -1) {
+ DEBUG(10, ("recv failed: %s\n", strerror(errno)));
+ goto sock_error;
+ }
+
+ DEBUG(11, ("cli_state_handler: received %d bytes, "
+ "smb_len(evt_inbuf) = %d\n", (int)res,
+ smb_len(cli->evt_inbuf)));
+
+ /* recv *might* have returned less than announced */
+ new_size = old_size + res;
+
+ /* shrink, so I don't expect errors here */
+ cli->evt_inbuf = TALLOC_REALLOC_ARRAY(cli, cli->evt_inbuf,
+ char, new_size);
+
+ while ((cli->evt_inbuf != NULL)
+ && ((smb_len(cli->evt_inbuf) + 4) <= new_size)) {
+ /*
+ * we've got a complete NBT level PDU in evt_inbuf
+ */
+ handle_incoming_pdu(cli);
+ new_size = talloc_get_size(cli->evt_inbuf);
+ }
+ }
+
+ if (flags & EVENT_FD_WRITE) {
+ size_t to_send;
+ ssize_t sent;
+
+ for (req = cli->outstanding_requests; req; req = req->next) {
+ to_send = smb_len(req->outbuf)+4;
+ if (to_send > req->sent) {
+ break;
+ }
+ }
+
+ if (req == NULL) {
+ event_fd_set_not_writeable(event);
+ return;
+ }
+
+ sent = send(cli->fd, req->outbuf + req->sent,
+ to_send - req->sent, 0);
+
+ if (sent < 0) {
+ goto sock_error;
+ }
+
+ req->sent += sent;
+
+ if (req->sent == to_send) {
+ return;
+ }
+ }
+ return;
+
+ sock_error:
+ for (req = cli->outstanding_requests; req; req = req->next) {
+ req->async->state = ASYNC_REQ_ERROR;
+ req->async->status = map_nt_error_from_unix(errno);
+ }
+ TALLOC_FREE(cli->fd_event);
+ close(cli->fd);
+ cli->fd = -1;
+}
+
+/*
+ * Holder for a talloc_destructor, we need to zero out the pointers in cli
+ * when deleting
+ */
+struct cli_tmp_event {
+ struct cli_state *cli;
+};
+
+static int cli_tmp_event_destructor(struct cli_tmp_event *e)
+{
+ TALLOC_FREE(e->cli->fd_event);
+ TALLOC_FREE(e->cli->event_ctx);
+ return 0;
+}
+
+/*
+ * Create a temporary event context for use in the sync helper functions
+ */
+
+struct cli_tmp_event *cli_tmp_event_ctx(TALLOC_CTX *mem_ctx,
+ struct cli_state *cli)
+{
+ struct cli_tmp_event *state;
+
+ if (cli->event_ctx != NULL) {
+ return NULL;
+ }
+
+ state = talloc(mem_ctx, struct cli_tmp_event);
+ if (state == NULL) {
+ return NULL;
+ }
+ state->cli = cli;
+ talloc_set_destructor(state, cli_tmp_event_destructor);
+
+ cli->event_ctx = event_context_init(state);
+ if (cli->event_ctx == NULL) {
+ TALLOC_FREE(state);
+ return NULL;
+ }
+
+ cli->fd_event = event_add_fd(cli->event_ctx, state, cli->fd,
+ EVENT_FD_READ, cli_state_handler, cli);
+ if (cli->fd_event == NULL) {
+ TALLOC_FREE(state);
+ return NULL;
+ }
+ return state;
+}
+
+/*
+ * Attach an event context permanently to a cli_struct
+ */
+
+NTSTATUS cli_add_event_ctx(struct cli_state *cli,
+ struct event_context *event_ctx)
+{
+ cli->event_ctx = event_ctx;
+ cli->fd_event = event_add_fd(event_ctx, cli, cli->fd, EVENT_FD_READ,
+ cli_state_handler, cli);
+ if (cli->fd_event == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ return NT_STATUS_OK;
+}
diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 4560521d4a..912b841d5e 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -581,8 +581,8 @@ static bool cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob, DATA_B
if (cli_is_error(cli) &&
!NT_STATUS_EQUAL( cli_get_nt_error(cli),
NT_STATUS_MORE_PROCESSING_REQUIRED)) {
- DEBUG(0, ("cli_session_setup_blob: recieve failed (%s)\n",
- nt_errstr(cli_get_nt_error(cli)) ));
+ DEBUG(0, ("cli_session_setup_blob: receive failed "
+ "(%s)\n", nt_errstr(cli_get_nt_error(cli))));
cli->vuid = 0;
return False;
}
@@ -627,7 +627,7 @@ static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli, const char *
if (!cli_session_setup_blob(cli, negTokenTarg, session_key_krb5)) {
data_blob_free(&negTokenTarg);
data_blob_free(&session_key_krb5);
- ADS_ERROR_NT(cli_nt_error(cli));
+ return ADS_ERROR_NT(cli_nt_error(cli));
}
cli_set_session_key(cli, session_key_krb5);
@@ -757,9 +757,9 @@ static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *use
/* 'resign' the last message, so we get the right sequence numbers
for checking the first reply from the server */
- cli_calculate_sign_mac(cli);
+ cli_calculate_sign_mac(cli, cli->outbuf);
- if (!cli_check_sign_mac(cli)) {
+ if (!cli_check_sign_mac(cli, cli->inbuf)) {
nt_status = NT_STATUS_ACCESS_DENIED;
}
}
@@ -872,13 +872,27 @@ ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
!strequal(star_smbserver_name,
cli->desthost)) {
char *realm = NULL;
+ char *machine = NULL;
+ char *host = NULL;
DEBUG(3,("cli_session_setup_spnego: got a "
"bad server principal, trying to guess ...\n"));
+ host = strchr_m(cli->desthost, '.');
+ if (host) {
+ machine = SMB_STRNDUP(cli->desthost,
+ host - cli->desthost);
+ } else {
+ machine = SMB_STRDUP(cli->desthost);
+ }
+ if (machine == NULL) {
+ return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
+ }
+
realm = kerberos_get_default_realm_from_ccache();
if (realm && *realm) {
if (asprintf(&principal, "%s$@%s",
- cli->desthost, realm) < 0) {
+ machine, realm) < 0) {
+ SAFE_FREE(machine);
SAFE_FREE(realm);
return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
}
@@ -886,6 +900,7 @@ ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
"server principal=%s\n",
principal ? principal : "<null>"));
}
+ SAFE_FREE(machine);
SAFE_FREE(realm);
}
diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c
index ecef293d07..64191239d3 100644
--- a/source3/libsmb/clientgen.c
+++ b/source3/libsmb/clientgen.c
@@ -69,15 +69,36 @@ int cli_set_port(struct cli_state *cli, int port)
static ssize_t client_receive_smb(struct cli_state *cli, size_t maxlen)
{
- ssize_t len;
+ size_t len;
for(;;) {
- len = receive_smb_raw(cli->fd, cli->inbuf, cli->timeout,
- maxlen, &cli->smb_rw_error);
+ NTSTATUS status;
- if (len < 0) {
+ set_smb_read_error(&cli->smb_rw_error, SMB_READ_OK);
+
+ status = receive_smb_raw(cli->fd, cli->inbuf, cli->timeout,
+ maxlen, &len);
+ if (!NT_STATUS_IS_OK(status)) {
DEBUG(10,("client_receive_smb failed\n"));
show_msg(cli->inbuf);
+
+ if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)) {
+ set_smb_read_error(&cli->smb_rw_error,
+ SMB_READ_EOF);
+ return -1;
+ }
+
+ if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
+ set_smb_read_error(&cli->smb_rw_error,
+ SMB_READ_TIMEOUT);
+ return -1;
+ }
+
+ set_smb_read_error(&cli->smb_rw_error, SMB_READ_ERROR);
+ return -1;
+ }
+
+ if (len < 0) {
return len;
}
@@ -143,7 +164,7 @@ bool cli_receive_smb(struct cli_state *cli)
return false;
}
- if (!cli_check_sign_mac(cli)) {
+ if (!cli_check_sign_mac(cli, cli->inbuf)) {
/*
* If we get a signature failure in sessionsetup, then
* the server sometimes just reflects the sent signature
@@ -180,12 +201,28 @@ bool cli_receive_smb(struct cli_state *cli)
ssize_t cli_receive_smb_data(struct cli_state *cli, char *buffer, size_t len)
{
- if (cli->timeout > 0) {
- return read_socket_with_timeout(cli->fd, buffer, len,
- len, cli->timeout, &cli->smb_rw_error);
- } else {
- return read_data(cli->fd, buffer, len, &cli->smb_rw_error);
+ NTSTATUS status;
+
+ set_smb_read_error(&cli->smb_rw_error, SMB_READ_OK);
+
+ status = read_socket_with_timeout(
+ cli->fd, buffer, len, len, cli->timeout, NULL);
+ if (NT_STATUS_IS_OK(status)) {
+ return len;
}
+
+ if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)) {
+ set_smb_read_error(&cli->smb_rw_error, SMB_READ_EOF);
+ return -1;
+ }
+
+ if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
+ set_smb_read_error(&cli->smb_rw_error, SMB_READ_TIMEOUT);
+ return -1;
+ }
+
+ set_smb_read_error(&cli->smb_rw_error, SMB_READ_ERROR);
+ return -1;
}
/****************************************************************************
@@ -306,10 +343,11 @@ bool cli_send_smb(struct cli_state *cli)
if (cli->fd == -1)
return false;
- cli_calculate_sign_mac(cli);
+ cli_calculate_sign_mac(cli, cli->outbuf);
if (enc_on) {
- NTSTATUS status = cli_encrypt_message(cli, &buf_out);
+ NTSTATUS status = cli_encrypt_message(cli, cli->outbuf,
+ &buf_out);
if (!NT_STATUS_IS_OK(status)) {
close(cli->fd);
cli->fd = -1;
@@ -412,31 +450,41 @@ bool cli_send_smb_direct_writeX(struct cli_state *cli,
Setup basics in a outgoing packet.
****************************************************************************/
-void cli_setup_packet(struct cli_state *cli)
+void cli_setup_packet_buf(struct cli_state *cli, char *buf)
{
+ uint16 flags2;
cli->rap_error = 0;
- SSVAL(cli->outbuf,smb_pid,cli->pid);
- SSVAL(cli->outbuf,smb_uid,cli->vuid);
- SSVAL(cli->outbuf,smb_mid,cli->mid);
- if (cli->protocol > PROTOCOL_CORE) {
- uint16 flags2;
- if (cli->case_sensitive) {
- SCVAL(cli->outbuf,smb_flg,0x0);
- } else {
- /* Default setting, case insensitive. */
- SCVAL(cli->outbuf,smb_flg,0x8);
- }
- flags2 = FLAGS2_LONG_PATH_COMPONENTS;
- if (cli->capabilities & CAP_UNICODE)
- flags2 |= FLAGS2_UNICODE_STRINGS;
- if ((cli->capabilities & CAP_DFS) && cli->dfsroot)
- flags2 |= FLAGS2_DFS_PATHNAMES;
- if (cli->capabilities & CAP_STATUS32)
- flags2 |= FLAGS2_32_BIT_ERROR_CODES;
- if (cli->use_spnego)
- flags2 |= FLAGS2_EXTENDED_SECURITY;
- SSVAL(cli->outbuf,smb_flg2, flags2);
+ SIVAL(buf,smb_rcls,0);
+ SSVAL(buf,smb_pid,cli->pid);
+ memset(buf+smb_pidhigh, 0, 12);
+ SSVAL(buf,smb_uid,cli->vuid);
+ SSVAL(buf,smb_mid,cli->mid);
+
+ if (cli->protocol <= PROTOCOL_CORE) {
+ return;
}
+
+ if (cli->case_sensitive) {
+ SCVAL(buf,smb_flg,0x0);
+ } else {
+ /* Default setting, case insensitive. */
+ SCVAL(buf,smb_flg,0x8);
+ }
+ flags2 = FLAGS2_LONG_PATH_COMPONENTS;
+ if (cli->capabilities & CAP_UNICODE)
+ flags2 |= FLAGS2_UNICODE_STRINGS;
+ if ((cli->capabilities & CAP_DFS) && cli->dfsroot)
+ flags2 |= FLAGS2_DFS_PATHNAMES;
+ if (cli->capabilities & CAP_STATUS32)
+ flags2 |= FLAGS2_32_BIT_ERROR_CODES;
+ if (cli->use_spnego)
+ flags2 |= FLAGS2_EXTENDED_SECURITY;
+ SSVAL(buf,smb_flg2, flags2);
+}
+
+void cli_setup_packet(struct cli_state *cli)
+{
+ cli_setup_packet_buf(cli, cli->outbuf);
}
/****************************************************************************
@@ -499,7 +547,7 @@ struct cli_state *cli_initialise(void)
return NULL;
}
- cli = SMB_MALLOC_P(struct cli_state);
+ cli = talloc(NULL, struct cli_state);
if (!cli) {
return NULL;
}
@@ -657,7 +705,7 @@ void cli_shutdown(struct cli_state *cli)
cli->fd = -1;
cli->smb_rw_error = SMB_READ_OK;
- SAFE_FREE(cli);
+ TALLOC_FREE(cli);
}
/****************************************************************************
diff --git a/source3/libsmb/clierror.c b/source3/libsmb/clierror.c
index 587abade59..36746419f7 100644
--- a/source3/libsmb/clierror.c
+++ b/source3/libsmb/clierror.c
@@ -483,3 +483,15 @@ void cli_set_nt_error(struct cli_state *cli, NTSTATUS status)
SSVAL(cli->inbuf,smb_flg2, SVAL(cli->inbuf,smb_flg2)|FLAGS2_32_BIT_ERROR_CODES);
SIVAL(cli->inbuf, smb_rcls, NT_STATUS_V(status));
}
+
+/* Reset an error. */
+
+void cli_reset_error(struct cli_state *cli)
+{
+ if (SVAL(cli->inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES) {
+ SIVAL(cli->inbuf, smb_rcls, NT_STATUS_V(NT_STATUS_OK));
+ } else {
+ SCVAL(cli->inbuf,smb_rcls,0);
+ SSVAL(cli->inbuf,smb_err,0);
+ }
+}
diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c
index 9b4c380d40..12c427a6fa 100644
--- a/source3/libsmb/clifile.c
+++ b/source3/libsmb/clifile.c
@@ -38,8 +38,15 @@ static bool cli_link_internal(struct cli_state *cli, const char *oldname, const
size_t newlen = 2*(strlen(newname)+1);
param = SMB_MALLOC_ARRAY(char, 6+newlen+2);
+
+ if (!param) {
+ return false;
+ }
+
data = SMB_MALLOC_ARRAY(char, oldlen+2);
- if (!param || !data) {
+
+ if (!data) {
+ SAFE_FREE(param);
return false;
}
@@ -882,6 +889,55 @@ bool cli_close(struct cli_state *cli, int fnum)
/****************************************************************************
+ Truncate a file to a specified size
+****************************************************************************/
+
+bool cli_ftruncate(struct cli_state *cli, int fnum, uint64_t size)
+{
+ unsigned int param_len = 6;
+ unsigned int data_len = 8;
+ uint16 setup = TRANSACT2_SETFILEINFO;
+ char param[6];
+ unsigned char data[8];
+ char *rparam=NULL, *rdata=NULL;
+ int saved_timeout = cli->timeout;
+
+ SSVAL(param,0,fnum);
+ SSVAL(param,2,SMB_SET_FILE_END_OF_FILE_INFO);
+ SSVAL(param,4,0);
+
+ SBVAL(data, 0, size);
+
+ if (!cli_send_trans(cli, SMBtrans2,
+ NULL, /* name */
+ -1, 0, /* fid, flags */
+ &setup, 1, 0, /* setup, length, max */
+ param, param_len, 2, /* param, length, max */
+ (char *)&data, data_len,/* data, length, ... */
+ cli->max_xmit)) { /* ... max */
+ cli->timeout = saved_timeout;
+ return False;
+ }
+
+ if (!cli_receive_trans(cli, SMBtrans2,
+ &rparam, &param_len,
+ &rdata, &data_len)) {
+ cli->timeout = saved_timeout;
+ SAFE_FREE(rdata);
+ SAFE_FREE(rparam);
+ return False;
+ }
+
+ cli->timeout = saved_timeout;
+
+ SAFE_FREE(rdata);
+ SAFE_FREE(rparam);
+
+ return True;
+}
+
+
+/****************************************************************************
send a lock with a specified locktype
this is used for testing LOCKING_ANDX_CANCEL_LOCK
****************************************************************************/
diff --git a/source3/libsmb/clifsinfo.c b/source3/libsmb/clifsinfo.c
index fb923378ab..0005c3908a 100644
--- a/source3/libsmb/clifsinfo.c
+++ b/source3/libsmb/clifsinfo.c
@@ -368,20 +368,16 @@ static struct smb_trans_enc_state *make_cli_enc_state(enum smb_trans_enc_type sm
ZERO_STRUCTP(es);
es->smb_enc_type = smb_enc_type;
- if (smb_enc_type == SMB_TRANS_ENC_GSS) {
#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
+ if (smb_enc_type == SMB_TRANS_ENC_GSS) {
es->s.gss_state = SMB_MALLOC_P(struct smb_tran_enc_state_gss);
if (!es->s.gss_state) {
SAFE_FREE(es);
return NULL;
}
ZERO_STRUCTP(es->s.gss_state);
-#else
- DEBUG(0,("make_cli_enc_state: no krb5 compiled.\n"));
- SAFE_FREE(es);
- return NULL;
-#endif
}
+#endif
return es;
}
@@ -497,8 +493,7 @@ static NTSTATUS make_cli_gss_blob(struct smb_trans_enc_state *es,
memset(&tok_out, '\0', sizeof(tok_out));
/* Get a ticket for the service@host */
- asprintf(&host_princ_s, "%s@%s", service, host);
- if (host_princ_s == NULL) {
+ if (asprintf(&host_princ_s, "%s@%s", service, host) == -1) {
return NT_STATUS_NO_MEMORY;
}
diff --git a/source3/libsmb/clikrb5.c b/source3/libsmb/clikrb5.c
index 844a3b35c0..c289740ab2 100644
--- a/source3/libsmb/clikrb5.c
+++ b/source3/libsmb/clikrb5.c
@@ -835,22 +835,22 @@ failed:
#endif
}
- void smb_krb5_checksum_from_pac_sig(krb5_checksum *cksum,
- PAC_SIGNATURE_DATA *sig)
+ void smb_krb5_checksum_from_pac_sig(krb5_checksum *cksum,
+ struct PAC_SIGNATURE_DATA *sig)
{
#ifdef HAVE_CHECKSUM_IN_KRB5_CHECKSUM
cksum->cksumtype = (krb5_cksumtype)sig->type;
- cksum->checksum.length = sig->signature.buf_len;
- cksum->checksum.data = sig->signature.buffer;
+ cksum->checksum.length = sig->signature.length;
+ cksum->checksum.data = sig->signature.data;
#else
cksum->checksum_type = (krb5_cksumtype)sig->type;
- cksum->length = sig->signature.buf_len;
- cksum->contents = sig->signature.buffer;
+ cksum->length = sig->signature.length;
+ cksum->contents = sig->signature.data;
#endif
}
krb5_error_code smb_krb5_verify_checksum(krb5_context context,
- krb5_keyblock *keyblock,
+ const krb5_keyblock *keyblock,
krb5_keyusage usage,
krb5_checksum *cksum,
uint8 *data,
diff --git a/source3/libsmb/clilist.c b/source3/libsmb/clilist.c
index d5c7db09e9..50918458b0 100644
--- a/source3/libsmb/clilist.c
+++ b/source3/libsmb/clilist.c
@@ -78,9 +78,20 @@ static size_t interpret_long_filename(TALLOC_CTX *ctx,
len = CVAL(p, 26);
p += 27;
p += clistr_align_in(cli, p, 0);
- if (p + len + 2 > pdata_end) {
+
+ /* We can safely use +1 here (which is required by OS/2)
+ * instead of +2 as the STR_TERMINATE flag below is
+ * actually used as the length calculation.
+ * The len+2 is merely an upper bound.
+ * Due to the explicit 2 byte null termination
+ * in cli_receive_trans/cli_receive_nt_trans
+ * we know this is safe. JRA + kukks
+ */
+
+ if (p + len + 1 > pdata_end) {
return pdata_end - base;
}
+
/* the len+2 below looks strange but it is
important to cope with the differences
between win2000 and win9x for this call
@@ -317,7 +328,7 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute,
&rparam, &param_len,
&rdata, &data_len) &&
cli_is_dos_error(cli)) {
- /* we need to work around a Win95 bug - sometimes
+ /* We need to work around a Win95 bug - sometimes
it gives ERRSRV/ERRerror temprarily */
uint8 eclass;
uint32 ecode;
@@ -326,6 +337,20 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute,
SAFE_FREE(rparam);
cli_dos_error(cli, &eclass, &ecode);
+
+ /*
+ * OS/2 might return "no more files",
+ * which just tells us, that searchcount is zero
+ * in this search.
+ * Guenter Kukkukk <linux@kukkukk.com>
+ */
+
+ if (eclass == ERRDOS && ecode == ERRnofiles) {
+ ff_searchcount = 0;
+ cli_reset_error(cli);
+ break;
+ }
+
if (eclass != ERRSRV || ecode != ERRerror)
break;
smb_msleep(100);
@@ -377,6 +402,12 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute,
&resume_key,
&last_name_raw);
+ if (!finfo.name) {
+ DEBUG(0,("cli_list_new: Error: unable to parse name from info level %d\n",
+ info_level));
+ ff_eos = 1;
+ break;
+ }
if (!First && *mask && strcsequal(finfo.name, mask)) {
DEBUG(0,("Error: Looping in FIND_NEXT as name %s has already been seen?\n",
finfo.name));
@@ -442,6 +473,11 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute,
&finfo,
NULL,
NULL);
+ if (!finfo.name) {
+ DEBUG(0,("cli_list_new: unable to parse name from info level %d\n",
+ info_level));
+ break;
+ }
fn(mnt,&finfo, Mask, state);
}
}
@@ -459,11 +495,12 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute,
The length of the structure is returned.
****************************************************************************/
-static int interpret_short_filename(TALLOC_CTX *ctx,
+static bool interpret_short_filename(TALLOC_CTX *ctx,
struct cli_state *cli,
char *p,
file_info *finfo)
{
+ size_t ret;
ZERO_STRUCTP(finfo);
finfo->cli = cli;
@@ -475,18 +512,22 @@ static int interpret_short_filename(TALLOC_CTX *ctx,
finfo->mtime_ts.tv_sec = finfo->atime_ts.tv_sec = finfo->ctime_ts.tv_sec;
finfo->mtime_ts.tv_nsec = finfo->atime_ts.tv_nsec = 0;
finfo->size = IVAL(p,26);
- clistr_pull_talloc(ctx,
+ ret = clistr_pull_talloc(ctx,
cli,
&finfo->name,
p+30,
12,
STR_ASCII);
- if (!finfo->name) {
- finfo->name = talloc_strdup(ctx, finfo->short_name);
- } else if (strcmp(finfo->name, "..") && strcmp(finfo->name, ".")) {
- finfo->name = talloc_strdup(ctx, finfo->short_name);
+ if (ret == (size_t)-1) {
+ return false;
}
+ if (finfo->name) {
+ strlcpy(finfo->short_name,
+ finfo->name,
+ sizeof(finfo->short_name));
+ }
+ return true;
return(DIR_STRUCT_SIZE);
}
@@ -555,6 +596,12 @@ int cli_list_old(struct cli_state *cli,const char *Mask,uint16 attribute,
received = SVAL(cli->inbuf,smb_vwv0);
if (received <= 0) break;
+ /* Ensure we received enough data. */
+ if ((cli->inbuf+4+smb_len(cli->inbuf) - (smb_buf(cli->inbuf)+3)) <
+ received*DIR_STRUCT_SIZE) {
+ break;
+ }
+
first = False;
dirlist = (char *)SMB_REALLOC(
@@ -609,7 +656,10 @@ int cli_list_old(struct cli_state *cli,const char *Mask,uint16 attribute,
frame = talloc_stackframe();
for (p=dirlist,i=0;i<num_received;i++) {
file_info finfo;
- p += interpret_short_filename(frame,cli, p,&finfo);
+ if (!interpret_short_filename(frame, cli, p, &finfo)) {
+ break;
+ }
+ p += DIR_STRUCT_SIZE;
fn("\\", &finfo, Mask, state);
}
TALLOC_FREE(frame);
diff --git a/source3/libsmb/clirap.c b/source3/libsmb/clirap.c
index aab77a3d54..8c167e1257 100644
--- a/source3/libsmb/clirap.c
+++ b/source3/libsmb/clirap.c
@@ -191,12 +191,13 @@ int cli_RNetShareEnum(struct cli_state *cli, void (*fn)(const char *, uint32, co
sname = p;
type = SVAL(p,14);
- comment_offset = IVAL(p,16) & 0xFFFF;
- if (comment_offset < 0 || comment_offset > (int)rdrcnt) {
+ comment_offset = (IVAL(p,16) & 0xFFFF) - converter;
+ if (comment_offset < 0 ||
+ comment_offset > (int)rdrcnt) {
TALLOC_FREE(frame);
break;
}
- cmnt = comment_offset?(rdata+comment_offset-converter):"";
+ cmnt = comment_offset?(rdata+comment_offset):"";
/* Work out the comment length. */
for (p1 = cmnt, len = 0; *p1 &&
@@ -806,6 +807,137 @@ bool cli_qpathinfo2(struct cli_state *cli, const char *fname,
}
/****************************************************************************
+ Get the stream info
+****************************************************************************/
+
+bool cli_qpathinfo_streams(struct cli_state *cli, const char *fname,
+ TALLOC_CTX *mem_ctx,
+ unsigned int *pnum_streams,
+ struct stream_struct **pstreams)
+{
+ unsigned int data_len = 0;
+ unsigned int param_len = 0;
+ uint16 setup = TRANSACT2_QPATHINFO;
+ char *param;
+ char *rparam=NULL, *rdata=NULL;
+ char *p;
+ unsigned int num_streams;
+ struct stream_struct *streams;
+ unsigned int ofs;
+ size_t namelen = 2*(strlen(fname)+1);
+
+ param = SMB_MALLOC_ARRAY(char, 6+namelen+2);
+ if (param == NULL) {
+ return false;
+ }
+ p = param;
+ memset(p, 0, 6);
+ SSVAL(p, 0, SMB_FILE_STREAM_INFORMATION);
+ p += 6;
+ p += clistr_push(cli, p, fname, namelen, STR_TERMINATE);
+
+ param_len = PTR_DIFF(p, param);
+
+ if (!cli_send_trans(cli, SMBtrans2,
+ NULL, /* name */
+ -1, 0, /* fid, flags */
+ &setup, 1, 0, /* setup, len, max */
+ param, param_len, 10, /* param, len, max */
+ NULL, data_len, cli->max_xmit /* data, len, max */
+ )) {
+ return false;
+ }
+
+ if (!cli_receive_trans(cli, SMBtrans2,
+ &rparam, &param_len,
+ &rdata, &data_len)) {
+ return false;
+ }
+
+ if (!rdata) {
+ SAFE_FREE(rparam);
+ return false;
+ }
+
+ num_streams = 0;
+ streams = NULL;
+ ofs = 0;
+
+ while ((data_len > ofs) && (data_len - ofs >= 24)) {
+ uint32_t nlen, len;
+ ssize_t size;
+ void *vstr;
+ struct stream_struct *tmp;
+ uint8_t *tmp_buf;
+
+ tmp = TALLOC_REALLOC_ARRAY(mem_ctx, streams,
+ struct stream_struct,
+ num_streams+1);
+
+ if (tmp == NULL) {
+ goto fail;
+ }
+ streams = tmp;
+
+ nlen = IVAL(rdata, ofs + 0x04);
+
+ streams[num_streams].size = IVAL_TO_SMB_OFF_T(
+ rdata, ofs + 0x08);
+ streams[num_streams].alloc_size = IVAL_TO_SMB_OFF_T(
+ rdata, ofs + 0x10);
+
+ if (nlen > data_len - (ofs + 24)) {
+ goto fail;
+ }
+
+ /*
+ * We need to null-terminate src, how do I do this with
+ * convert_string_talloc??
+ */
+
+ tmp_buf = TALLOC_ARRAY(streams, uint8_t, nlen+2);
+ if (tmp_buf == NULL) {
+ goto fail;
+ }
+
+ memcpy(tmp_buf, rdata+ofs+24, nlen);
+ tmp_buf[nlen] = 0;
+ tmp_buf[nlen+1] = 0;
+
+ size = convert_string_talloc(streams, CH_UTF16, CH_UNIX,
+ tmp_buf, nlen+2, &vstr,
+ false);
+ TALLOC_FREE(tmp_buf);
+
+ if (size == -1) {
+ goto fail;
+ }
+ streams[num_streams].name = (char *)vstr;
+ num_streams++;
+
+ len = IVAL(rdata, ofs);
+ if (len > data_len - ofs) {
+ goto fail;
+ }
+ if (len == 0) break;
+ ofs += len;
+ }
+
+ SAFE_FREE(rdata);
+ SAFE_FREE(rparam);
+
+ *pnum_streams = num_streams;
+ *pstreams = streams;
+ return true;
+
+ fail:
+ TALLOC_FREE(streams);
+ SAFE_FREE(rdata);
+ SAFE_FREE(rparam);
+ return false;
+}
+
+/****************************************************************************
Send a qfileinfo QUERY_FILE_NAME_INFO call.
****************************************************************************/
diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c
index 6b39a885f0..c618509f01 100644
--- a/source3/libsmb/clireadwrite.c
+++ b/source3/libsmb/clireadwrite.c
@@ -20,167 +20,451 @@
#include "includes.h"
/****************************************************************************
-Issue a single SMBread and don't wait for a reply.
+ Calculate the recommended read buffer size
****************************************************************************/
+static size_t cli_read_max_bufsize(struct cli_state *cli)
+{
+ if (!client_is_signing_on(cli) && !cli_encryption_on(cli) == false
+ && (cli->posix_capabilities & CIFS_UNIX_LARGE_READ_CAP)) {
+ return CLI_SAMBA_MAX_POSIX_LARGE_READX_SIZE;
+ }
+ if (cli->capabilities & CAP_LARGE_READX) {
+ return cli->is_samba
+ ? CLI_SAMBA_MAX_LARGE_READX_SIZE
+ : CLI_WINDOWS_MAX_LARGE_READX_SIZE;
+ }
+ return (cli->max_xmit - (smb_size+32)) & ~1023;
+}
-static bool cli_issue_read(struct cli_state *cli, int fnum, off_t offset,
- size_t size, int i)
+/*
+ * Send a read&x request
+ */
+
+struct async_req *cli_read_andx_send(TALLOC_CTX *mem_ctx,
+ struct cli_state *cli, int fnum,
+ off_t offset, size_t size)
{
+ struct async_req *result;
+ struct cli_request *req;
bool bigoffset = False;
+ char *enc_buf;
- memset(cli->outbuf,'\0',smb_size);
- memset(cli->inbuf,'\0',smb_size);
+ if (size > cli_read_max_bufsize(cli)) {
+ DEBUG(0, ("cli_read_andx_send got size=%d, can only handle "
+ "size=%d\n", (int)size,
+ (int)cli_read_max_bufsize(cli)));
+ return NULL;
+ }
+
+ result = cli_request_new(mem_ctx, cli->event_ctx, cli, 12, 0, &req);
+ if (result == NULL) {
+ DEBUG(0, ("cli_request_new failed\n"));
+ return NULL;
+ }
+
+ req = cli_request_get(result);
+
+ req->data.read.ofs = offset;
+ req->data.read.size = size;
+ req->data.read.received = 0;
+ req->data.read.rcvbuf = NULL;
if ((SMB_BIG_UINT)offset >> 32)
bigoffset = True;
- cli_set_message(cli->outbuf,bigoffset ? 12 : 10,0,True);
+ cli_set_message(req->outbuf, bigoffset ? 12 : 10, 0, False);
- SCVAL(cli->outbuf,smb_com,SMBreadX);
- SSVAL(cli->outbuf,smb_tid,cli->cnum);
- cli_setup_packet(cli);
+ SCVAL(req->outbuf,smb_com,SMBreadX);
+ SSVAL(req->outbuf,smb_tid,cli->cnum);
+ cli_setup_packet_buf(cli, req->outbuf);
- SCVAL(cli->outbuf,smb_vwv0,0xFF);
- SSVAL(cli->outbuf,smb_vwv2,fnum);
- SIVAL(cli->outbuf,smb_vwv3,offset);
- SSVAL(cli->outbuf,smb_vwv5,size);
- SSVAL(cli->outbuf,smb_vwv6,size);
- SSVAL(cli->outbuf,smb_vwv7,(size >> 16));
- SSVAL(cli->outbuf,smb_mid,cli->mid + i);
+ SCVAL(req->outbuf,smb_vwv0,0xFF);
+ SCVAL(req->outbuf,smb_vwv0+1,0);
+ SSVAL(req->outbuf,smb_vwv1,0);
+ SSVAL(req->outbuf,smb_vwv2,fnum);
+ SIVAL(req->outbuf,smb_vwv3,offset);
+ SSVAL(req->outbuf,smb_vwv5,size);
+ SSVAL(req->outbuf,smb_vwv6,size);
+ SSVAL(req->outbuf,smb_vwv7,(size >> 16));
+ SSVAL(req->outbuf,smb_vwv8,0);
+ SSVAL(req->outbuf,smb_vwv9,0);
+ SSVAL(req->outbuf,smb_mid,req->mid);
if (bigoffset) {
- SIVAL(cli->outbuf,smb_vwv10,(((SMB_BIG_UINT)offset)>>32) & 0xffffffff);
+ SIVAL(req->outbuf, smb_vwv10,
+ (((SMB_BIG_UINT)offset)>>32) & 0xffffffff);
}
- return cli_send_smb(cli);
-}
+ cli_calculate_sign_mac(cli, req->outbuf);
-/****************************************************************************
- Read size bytes at offset offset using SMBreadX.
-****************************************************************************/
+ event_fd_set_writeable(cli->fd_event);
+
+ if (cli_encryption_on(cli)) {
+ NTSTATUS status;
+ status = cli_encrypt_message(cli, req->outbuf, &enc_buf);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("Error in encrypting client message. "
+ "Error %s\n", nt_errstr(status)));
+ TALLOC_FREE(req);
+ return NULL;
+ }
+ req->outbuf = enc_buf;
+ req->enc_state = cli->trans_enc_state;
+ }
-ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_t size)
+ return result;
+}
+
+/*
+ * Pull the data out of a finished async read_and_x request. rcvbuf is
+ * talloced from the request, so better make sure that you copy it away before
+ * you talloc_free(req). "rcvbuf" is NOT a talloc_ctx of its own, so do not
+ * talloc_move it!
+ */
+
+NTSTATUS cli_read_andx_recv(struct async_req *req, ssize_t *received,
+ uint8_t **rcvbuf)
{
- char *p;
- size_t size2;
- size_t readsize;
- ssize_t total = 0;
- /* We can only do direct reads if not signing or encrypting. */
- bool direct_reads = !client_is_signing_on(cli) && !cli_encryption_on(cli);
+ struct cli_request *cli_req = cli_request_get(req);
+ NTSTATUS status;
+ size_t size;
- if (size == 0)
- return 0;
+ SMB_ASSERT(req->state >= ASYNC_REQ_DONE);
+ if (req->state == ASYNC_REQ_ERROR) {
+ return req->status;
+ }
+
+ status = cli_pull_error(cli_req->inbuf);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ /* size is the number of bytes the server returned.
+ * Might be zero. */
+ size = SVAL(cli_req->inbuf, smb_vwv5);
+ size |= (((unsigned int)(SVAL(cli_req->inbuf, smb_vwv7))) << 16);
+
+ if (size > cli_req->data.read.size) {
+ DEBUG(5,("server returned more than we wanted!\n"));
+ return NT_STATUS_UNEXPECTED_IO_ERROR;
+ }
+
+ if (size < 0) {
+ DEBUG(5,("read return < 0!\n"));
+ return NT_STATUS_UNEXPECTED_IO_ERROR;
+ }
+
+ *rcvbuf = (uint8_t *)
+ (smb_base(cli_req->inbuf) + SVAL(cli_req->inbuf, smb_vwv6));
+ *received = size;
+ return NT_STATUS_OK;
+}
+
+/*
+ * Parallel read support.
+ *
+ * cli_pull sends as many read&x requests as the server would allow via
+ * max_mux at a time. When replies flow back in, the data is written into
+ * the callback function "sink" in the right order.
+ */
+
+struct cli_pull_state {
+ struct async_req *req;
+
+ struct cli_state *cli;
+ uint16_t fnum;
+ off_t start_offset;
+ size_t size;
+
+ NTSTATUS (*sink)(char *buf, size_t n, void *priv);
+ void *priv;
+
+ size_t chunk_size;
/*
- * Set readsize to the maximum size we can handle in one readX,
- * rounded down to a multiple of 1024.
+ * Outstanding requests
*/
+ int num_reqs;
+ struct async_req **reqs;
- if (client_is_signing_on(cli) == false &&
- cli_encryption_on(cli) == false &&
- (cli->posix_capabilities & CIFS_UNIX_LARGE_READ_CAP)) {
- readsize = CLI_SAMBA_MAX_POSIX_LARGE_READX_SIZE;
- } else if (cli->capabilities & CAP_LARGE_READX) {
- if (cli->is_samba) {
- readsize = CLI_SAMBA_MAX_LARGE_READX_SIZE;
- } else {
- readsize = CLI_WINDOWS_MAX_LARGE_READX_SIZE;
- }
- } else {
- readsize = (cli->max_xmit - (smb_size+32)) & ~1023;
+ /*
+ * For how many bytes did we send requests already?
+ */
+ off_t requested;
+
+ /*
+ * Next request index to push into "sink". This walks around the "req"
+ * array, taking care that the requests are pushed to "sink" in the
+ * right order. If necessary (i.e. replies don't come in in the right
+ * order), replies are held back in "reqs".
+ */
+ int top_req;
+
+ /*
+ * How many bytes did we push into "sink"?
+ */
+
+ off_t pushed;
+};
+
+static char *cli_pull_print(TALLOC_CTX *mem_ctx, struct async_req *req)
+{
+ struct cli_pull_state *state = talloc_get_type_abort(
+ req->private_data, struct cli_pull_state);
+ char *result;
+
+ result = async_req_print(mem_ctx, req);
+ if (result == NULL) {
+ return NULL;
}
- while (total < size) {
- readsize = MIN(readsize, size-total);
+ return talloc_asprintf_append_buffer(
+ result, "num_reqs=%d, top_req=%d",
+ state->num_reqs, state->top_req);
+}
- /* Issue a read and receive a reply */
+static void cli_pull_read_done(struct async_req *read_req);
- if (!cli_issue_read(cli, fnum, offset, readsize, 0))
- return -1;
+/*
+ * Prepare an async pull request
+ */
+
+struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, struct cli_state *cli,
+ uint16_t fnum, off_t start_offset,
+ size_t size, size_t window_size,
+ NTSTATUS (*sink)(char *buf, size_t n,
+ void *priv),
+ void *priv)
+{
+ struct async_req *result;
+ struct cli_pull_state *state;
+ int i;
- if (direct_reads) {
- if (!cli_receive_smb_readX_header(cli))
- return -1;
- } else {
- if (!cli_receive_smb(cli))
- return -1;
+ result = async_req_new(mem_ctx, cli->event_ctx);
+ if (result == NULL) {
+ goto failed;
+ }
+ state = talloc(result, struct cli_pull_state);
+ if (state == NULL) {
+ goto failed;
+ }
+ result->private_data = state;
+ result->print = cli_pull_print;
+ state->req = result;
+
+ state->cli = cli;
+ state->fnum = fnum;
+ state->start_offset = start_offset;
+ state->size = size;
+ state->sink = sink;
+ state->priv = priv;
+
+ state->pushed = 0;
+ state->top_req = 0;
+ state->chunk_size = cli_read_max_bufsize(cli);
+
+ state->num_reqs = MAX(window_size/state->chunk_size, 1);
+ state->num_reqs = MIN(state->num_reqs, cli->max_mux);
+
+ state->reqs = TALLOC_ZERO_ARRAY(state, struct async_req *,
+ state->num_reqs);
+ if (state->reqs == NULL) {
+ goto failed;
+ }
+
+ state->requested = 0;
+
+ for (i=0; i<state->num_reqs; i++) {
+ size_t size_left, request_thistime;
+
+ if (state->requested >= size) {
+ state->num_reqs = i;
+ break;
}
- /* Check for error. Make sure to check for DOS and NT
- errors. */
+ size_left = size - state->requested;
+ request_thistime = MIN(size_left, state->chunk_size);
- if (cli_is_error(cli)) {
- bool recoverable_error = False;
- NTSTATUS status = NT_STATUS_OK;
- uint8 eclass = 0;
- uint32 ecode = 0;
+ state->reqs[i] = cli_read_andx_send(
+ state->reqs, cli, fnum,
+ state->start_offset + state->requested,
+ request_thistime);
- if (cli_is_nt_error(cli))
- status = cli_nt_error(cli);
- else
- cli_dos_error(cli, &eclass, &ecode);
+ if (state->reqs[i] == NULL) {
+ goto failed;
+ }
- /*
- * ERRDOS ERRmoredata or STATUS_MORE_ENRTIES is a
- * recoverable error, plus we have valid data in the
- * packet so don't error out here.
- */
+ state->reqs[i]->async.fn = cli_pull_read_done;
+ state->reqs[i]->async.priv = result;
- if ((eclass == ERRDOS && ecode == ERRmoredata) ||
- NT_STATUS_V(status) == NT_STATUS_V(STATUS_MORE_ENTRIES))
- recoverable_error = True;
+ state->requested += request_thistime;
+ }
+ return result;
- if (!recoverable_error)
- return -1;
+failed:
+ TALLOC_FREE(result);
+ return NULL;
+}
+
+/*
+ * Handle incoming read replies, push the data into sink and send out new
+ * requests if necessary.
+ */
+
+static void cli_pull_read_done(struct async_req *read_req)
+{
+ struct async_req *pull_req = talloc_get_type_abort(
+ read_req->async.priv, struct async_req);
+ struct cli_pull_state *state = talloc_get_type_abort(
+ pull_req->private_data, struct cli_pull_state);
+ struct cli_request *read_state = cli_request_get(read_req);
+ NTSTATUS status;
+
+ status = cli_read_andx_recv(read_req, &read_state->data.read.received,
+ &read_state->data.read.rcvbuf);
+ if (!NT_STATUS_IS_OK(status)) {
+ async_req_error(state->req, status);
+ return;
+ }
+
+ /*
+ * This loop is the one to take care of out-of-order replies. All
+ * pending requests are in state->reqs, state->reqs[top_req] is the
+ * one that is to be pushed next. If however a request later than
+ * top_req is replied to, then we can't push yet. If top_req is
+ * replied to at a later point then, we need to push all the finished
+ * requests.
+ */
+
+ while (state->reqs[state->top_req] != NULL) {
+ struct cli_request *top_read;
+
+ DEBUG(11, ("cli_pull_read_done: top_req = %d\n",
+ state->top_req));
+
+ if (state->reqs[state->top_req]->state < ASYNC_REQ_DONE) {
+ DEBUG(11, ("cli_pull_read_done: top request not yet "
+ "done\n"));
+ return;
}
- size2 = SVAL(cli->inbuf, smb_vwv5);
- size2 |= (((unsigned int)(SVAL(cli->inbuf, smb_vwv7))) << 16);
+ top_read = cli_request_get(state->reqs[state->top_req]);
- if (size2 > readsize) {
- DEBUG(5,("server returned more than we wanted!\n"));
- return -1;
- } else if (size2 < 0) {
- DEBUG(5,("read return < 0!\n"));
- return -1;
+ DEBUG(10, ("cli_pull_read_done: Pushing %d bytes, %d already "
+ "pushed\n", (int)top_read->data.read.received,
+ (int)state->pushed));
+
+ status = state->sink((char *)top_read->data.read.rcvbuf,
+ top_read->data.read.received,
+ state->priv);
+ if (!NT_STATUS_IS_OK(status)) {
+ async_req_error(state->req, status);
+ return;
}
+ state->pushed += top_read->data.read.received;
- if (!direct_reads) {
- /* Copy data into buffer */
- p = smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_vwv6);
- memcpy(buf + total, p, size2);
- } else {
- /* Ensure the remaining data matches the return size. */
- ssize_t toread = smb_len_large(cli->inbuf) - SVAL(cli->inbuf,smb_vwv6);
-
- /* Ensure the size is correct. */
- if (toread != size2) {
- DEBUG(5,("direct read logic fail toread (%d) != size2 (%u)\n",
- (int)toread, (unsigned int)size2 ));
- return -1;
- }
+ TALLOC_FREE(state->reqs[state->top_req]);
- /* Read data directly into buffer */
- toread = cli_receive_smb_data(cli,buf+total,size2);
- if (toread != size2) {
- DEBUG(5,("direct read read failure toread (%d) != size2 (%u)\n",
- (int)toread, (unsigned int)size2 ));
- return -1;
+ if (state->requested < state->size) {
+ struct async_req *new_req;
+ size_t size_left, request_thistime;
+
+ size_left = state->size - state->requested;
+ request_thistime = MIN(size_left, state->chunk_size);
+
+ DEBUG(10, ("cli_pull_read_done: Requesting %d bytes "
+ "at %d, position %d\n",
+ (int)request_thistime,
+ (int)(state->start_offset
+ + state->requested),
+ state->top_req));
+
+ new_req = cli_read_andx_send(
+ state->reqs, state->cli, state->fnum,
+ state->start_offset + state->requested,
+ request_thistime);
+
+ if (async_req_nomem(new_req, state->req)) {
+ return;
}
+
+ new_req->async.fn = cli_pull_read_done;
+ new_req->async.priv = pull_req;
+
+ state->reqs[state->top_req] = new_req;
+ state->requested += request_thistime;
}
- total += size2;
- offset += size2;
+ state->top_req = (state->top_req+1) % state->num_reqs;
+ }
- /*
- * If the server returned less than we asked for we're at EOF.
- */
+ async_req_done(pull_req);
+}
- if (size2 < readsize)
- break;
+NTSTATUS cli_pull_recv(struct async_req *req, ssize_t *received)
+{
+ struct cli_pull_state *state = talloc_get_type_abort(
+ req->private_data, struct cli_pull_state);
+
+ SMB_ASSERT(req->state >= ASYNC_REQ_DONE);
+ if (req->state == ASYNC_REQ_ERROR) {
+ return req->status;
}
+ *received = state->pushed;
+ return NT_STATUS_OK;
+}
- return total;
+NTSTATUS cli_pull(struct cli_state *cli, uint16_t fnum,
+ off_t start_offset, size_t size, size_t window_size,
+ NTSTATUS (*sink)(char *buf, size_t n, void *priv),
+ void *priv, ssize_t *received)
+{
+ TALLOC_CTX *frame = talloc_stackframe();
+ struct async_req *req;
+ NTSTATUS result = NT_STATUS_NO_MEMORY;
+
+ if (cli_tmp_event_ctx(frame, cli) == NULL) {
+ goto nomem;
+ }
+
+ req = cli_pull_send(frame, cli, fnum, start_offset, size, window_size,
+ sink, priv);
+ if (req == NULL) {
+ goto nomem;
+ }
+
+ while (req->state < ASYNC_REQ_DONE) {
+ event_loop_once(cli->event_ctx);
+ }
+
+ result = cli_pull_recv(req, received);
+ nomem:
+ TALLOC_FREE(frame);
+ return result;
+}
+
+static NTSTATUS cli_read_sink(char *buf, size_t n, void *priv)
+{
+ char **pbuf = (char **)priv;
+ memcpy(*pbuf, buf, n);
+ *pbuf += n;
+ return NT_STATUS_OK;
+}
+
+ssize_t cli_read(struct cli_state *cli, int fnum, char *buf,
+ off_t offset, size_t size)
+{
+ NTSTATUS status;
+ ssize_t ret;
+
+ status = cli_pull(cli, fnum, offset, size, size,
+ cli_read_sink, &buf, &ret);
+ if (!NT_STATUS_IS_OK(status)) {
+ cli_set_error(cli, status);
+ return -1;
+ }
+ return ret;
}
#if 0 /* relies on client_receive_smb(), now a static in libsmb/clientgen.c */
diff --git a/source3/libsmb/clispnego.c b/source3/libsmb/clispnego.c
index f95b11e4cd..a75032a47d 100644
--- a/source3/libsmb/clispnego.c
+++ b/source3/libsmb/clispnego.c
@@ -498,11 +498,13 @@ DATA_BLOB spnego_gen_auth_response(DATA_BLOB *reply, NTSTATUS nt_status,
asn1_write_enumerated(&data, negResult);
asn1_pop_tag(&data);
- if (reply->data != NULL) {
+ if (mechOID) {
asn1_push_tag(&data,ASN1_CONTEXT(1));
asn1_write_OID(&data, mechOID);
asn1_pop_tag(&data);
-
+ }
+
+ if (reply && reply->data != NULL) {
asn1_push_tag(&data,ASN1_CONTEXT(2));
asn1_write_OctetString(&data, reply->data, reply->length);
asn1_pop_tag(&data);
diff --git a/source3/libsmb/credentials.c b/source3/libsmb/credentials.c
index 1256a6210e..9d33e6d93d 100644
--- a/source3/libsmb/credentials.c
+++ b/source3/libsmb/credentials.c
@@ -42,9 +42,9 @@ char *credstr(const unsigned char *cred)
****************************************************************************/
static void creds_init_128(struct dcinfo *dc,
- const DOM_CHAL *clnt_chal_in,
- const DOM_CHAL *srv_chal_in,
- const unsigned char mach_pw[16])
+ const struct netr_Credential *clnt_chal_in,
+ const struct netr_Credential *srv_chal_in,
+ const unsigned char mach_pw[16])
{
unsigned char zero[4], tmp[16];
HMACMD5Context ctx;
@@ -94,9 +94,9 @@ static void creds_init_128(struct dcinfo *dc,
****************************************************************************/
static void creds_init_64(struct dcinfo *dc,
- const DOM_CHAL *clnt_chal_in,
- const DOM_CHAL *srv_chal_in,
- const unsigned char mach_pw[16])
+ const struct netr_Credential *clnt_chal_in,
+ const struct netr_Credential *srv_chal_in,
+ const unsigned char mach_pw[16])
{
uint32 sum[2];
unsigned char sum2[8];
@@ -177,10 +177,10 @@ static void creds_step(struct dcinfo *dc)
void creds_server_init(uint32 neg_flags,
struct dcinfo *dc,
- DOM_CHAL *clnt_chal,
- DOM_CHAL *srv_chal,
+ struct netr_Credential *clnt_chal,
+ struct netr_Credential *srv_chal,
const unsigned char mach_pw[16],
- DOM_CHAL *init_chal_out)
+ struct netr_Credential *init_chal_out)
{
DEBUG(10,("creds_server_init: neg_flags : %x\n", (unsigned int)neg_flags));
DEBUG(10,("creds_server_init: client chal : %s\n", credstr(clnt_chal->data) ));
@@ -213,25 +213,28 @@ void creds_server_init(uint32 neg_flags,
Check a credential sent by the client.
****************************************************************************/
-bool creds_server_check(const struct dcinfo *dc, const DOM_CHAL *rcv_cli_chal_in)
+bool netlogon_creds_server_check(const struct dcinfo *dc,
+ const struct netr_Credential *rcv_cli_chal_in)
{
if (memcmp(dc->clnt_chal.data, rcv_cli_chal_in->data, 8)) {
- DEBUG(5,("creds_server_check: challenge : %s\n", credstr(rcv_cli_chal_in->data)));
+ DEBUG(5,("netlogon_creds_server_check: challenge : %s\n",
+ credstr(rcv_cli_chal_in->data)));
DEBUG(5,("calculated: %s\n", credstr(dc->clnt_chal.data)));
- DEBUG(2,("creds_server_check: credentials check failed.\n"));
- return False;
+ DEBUG(2,("netlogon_creds_server_check: credentials check failed.\n"));
+ return false;
}
- DEBUG(10,("creds_server_check: credentials check OK.\n"));
- return True;
-}
+ DEBUG(10,("netlogon_creds_server_check: credentials check OK.\n"));
+
+ return true;
+}
/****************************************************************************
Replace current seed chal. Internal function - due to split server step below.
****************************************************************************/
static void creds_reseed(struct dcinfo *dc)
{
- DOM_CHAL time_chal;
+ struct netr_Credential time_chal;
SIVAL(time_chal.data, 0, IVAL(dc->seed_chal.data, 0) + dc->sequence + 1);
SIVAL(time_chal.data, 4, IVAL(dc->seed_chal.data, 4));
@@ -245,7 +248,9 @@ static void creds_reseed(struct dcinfo *dc)
Step the server credential chain one forward.
****************************************************************************/
-bool creds_server_step(struct dcinfo *dc, const DOM_CRED *received_cred, DOM_CRED *cred_out)
+bool netlogon_creds_server_step(struct dcinfo *dc,
+ const struct netr_Authenticator *received_cred,
+ struct netr_Authenticator *cred_out)
{
bool ret;
struct dcinfo tmp_dc = *dc;
@@ -253,24 +258,24 @@ bool creds_server_step(struct dcinfo *dc, const DOM_CRED *received_cred, DOM_CRE
/* Do all operations on a temporary copy of the dc,
which we throw away if the checks fail. */
- tmp_dc.sequence = received_cred->timestamp.time;
+ tmp_dc.sequence = received_cred->timestamp;
creds_step(&tmp_dc);
/* Create the outgoing credentials */
- cred_out->timestamp.time = tmp_dc.sequence + 1;
- cred_out->challenge = tmp_dc.srv_chal;
+ cred_out->timestamp = tmp_dc.sequence + 1;
+ memcpy(&cred_out->cred, &tmp_dc.srv_chal, sizeof(cred_out->cred));
creds_reseed(&tmp_dc);
- ret = creds_server_check(&tmp_dc, &received_cred->challenge);
+ ret = netlogon_creds_server_check(&tmp_dc, &received_cred->cred);
if (!ret) {
- return False;
+ return false;
}
/* creds step succeeded - replace the current creds. */
*dc = tmp_dc;
- return True;
+ return true;
}
/****************************************************************************
@@ -279,10 +284,10 @@ bool creds_server_step(struct dcinfo *dc, const DOM_CRED *received_cred, DOM_CRE
void creds_client_init(uint32 neg_flags,
struct dcinfo *dc,
- DOM_CHAL *clnt_chal,
- DOM_CHAL *srv_chal,
+ struct netr_Credential *clnt_chal,
+ struct netr_Credential *srv_chal,
const unsigned char mach_pw[16],
- DOM_CHAL *init_chal_out)
+ struct netr_Credential *init_chal_out)
{
dc->sequence = time(NULL);
@@ -317,18 +322,25 @@ void creds_client_init(uint32 neg_flags,
Check a credential returned by the server.
****************************************************************************/
-bool creds_client_check(const struct dcinfo *dc, const DOM_CHAL *rcv_srv_chal_in)
+bool netlogon_creds_client_check(const struct dcinfo *dc,
+ const struct netr_Credential *rcv_srv_chal_in)
{
- if (memcmp(dc->srv_chal.data, rcv_srv_chal_in->data, 8)) {
- DEBUG(5,("creds_client_check: challenge : %s\n", credstr(rcv_srv_chal_in->data)));
- DEBUG(5,("calculated: %s\n", credstr(dc->srv_chal.data)));
- DEBUG(0,("creds_client_check: credentials check failed.\n"));
- return False;
+ if (memcmp(dc->srv_chal.data, rcv_srv_chal_in->data,
+ sizeof(dc->srv_chal.data))) {
+
+ DEBUG(0,("netlogon_creds_client_check: credentials check failed.\n"));
+ DEBUGADD(5,("netlogon_creds_client_check: challenge : %s\n",
+ credstr(rcv_srv_chal_in->data)));
+ DEBUGADD(5,("calculated: %s\n", credstr(dc->srv_chal.data)));
+ return false;
}
- DEBUG(10,("creds_client_check: credentials check OK.\n"));
- return True;
+
+ DEBUG(10,("netlogon_creds_client_check: credentials check OK.\n"));
+
+ return true;
}
+
/****************************************************************************
Step the client credentials to the next element in the chain, updating the
current client and server credentials and the seed
@@ -336,12 +348,14 @@ bool creds_client_check(const struct dcinfo *dc, const DOM_CHAL *rcv_srv_chal_in
the server
****************************************************************************/
-void creds_client_step(struct dcinfo *dc, DOM_CRED *next_cred_out)
+void netlogon_creds_client_step(struct dcinfo *dc,
+ struct netr_Authenticator *next_cred_out)
{
- dc->sequence += 2;
+ dc->sequence += 2;
creds_step(dc);
creds_reseed(dc);
- next_cred_out->challenge = dc->clnt_chal;
- next_cred_out->timestamp.time = dc->sequence;
+ memcpy(&next_cred_out->cred.data, &dc->clnt_chal.data,
+ sizeof(next_cred_out->cred.data));
+ next_cred_out->timestamp = dc->sequence;
}
diff --git a/source3/libsmb/doserr.c b/source3/libsmb/doserr.c
index 79445a2410..203f682599 100644
--- a/source3/libsmb/doserr.c
+++ b/source3/libsmb/doserr.c
@@ -73,8 +73,9 @@ werror_code_struct dos_errs[] =
{ "WERR_DFS_NO_SUCH_SERVER", WERR_DFS_NO_SUCH_SERVER },
{ "WERR_DFS_INTERNAL_ERROR", WERR_DFS_INTERNAL_ERROR },
{ "WERR_DFS_CANT_CREATE_JUNCT", WERR_DFS_CANT_CREATE_JUNCT },
+ { "WERR_INVALID_COMPUTER_NAME", WERR_INVALID_COMPUTER_NAME },
{ "WERR_MACHINE_LOCKED", WERR_MACHINE_LOCKED },
- { "WERR_DOMAIN_CONTROLLER_NOT_FOUND", WERR_DOMAIN_CONTROLLER_NOT_FOUND },
+ { "WERR_DC_NOT_FOUND", WERR_DC_NOT_FOUND },
{ "WERR_SETUP_NOT_JOINED", WERR_SETUP_NOT_JOINED },
{ "WERR_SETUP_ALREADY_JOINED", WERR_SETUP_ALREADY_JOINED },
{ "WERR_SETUP_DOMAIN_CONTROLLER", WERR_SETUP_DOMAIN_CONTROLLER },
@@ -83,6 +84,7 @@ werror_code_struct dos_errs[] =
{ "WERR_LOGON_FAILURE", WERR_LOGON_FAILURE },
{ "WERR_NO_SUCH_DOMAIN", WERR_NO_SUCH_DOMAIN },
{ "WERR_INVALID_SECURITY_DESCRIPTOR", WERR_INVALID_SECURITY_DESCRIPTOR },
+ { "WERR_TIME_SKEW", WERR_TIME_SKEW },
{ "WERR_INVALID_OWNER", WERR_INVALID_OWNER },
{ "WERR_SERVER_UNAVAILABLE", WERR_SERVER_UNAVAILABLE },
{ "WERR_IO_PENDING", WERR_IO_PENDING },
@@ -96,6 +98,9 @@ werror_code_struct dos_errs[] =
{ "WERR_SERVICE_DISABLED", WERR_SERVICE_DISABLED },
{ "WERR_CAN_NOT_COMPLETE", WERR_CAN_NOT_COMPLETE},
{ "WERR_INVALID_FLAGS", WERR_INVALID_FLAGS},
+ { "WERR_PASSWORD_MUST_CHANGE", WERR_PASSWORD_MUST_CHANGE },
+ { "WERR_DOMAIN_CONTROLLER_NOT_FOUND", WERR_DOMAIN_CONTROLLER_NOT_FOUND },
+ { "WERR_ACCOUNT_LOCKED_OUT", WERR_ACCOUNT_LOCKED_OUT },
{ NULL, W_ERROR(0) }
};
@@ -109,11 +114,15 @@ werror_str_struct dos_err_strs[] = {
{ WERR_NO_LOGON_SERVERS, "No logon servers found" },
{ WERR_NO_SUCH_LOGON_SESSION, "No such logon session" },
{ WERR_DOMAIN_CONTROLLER_NOT_FOUND, "A domain controller could not be found" },
+ { WERR_DC_NOT_FOUND, "A domain controller could not be found" },
{ WERR_SETUP_NOT_JOINED, "Join failed" },
{ WERR_SETUP_ALREADY_JOINED, "Machine is already joined" },
{ WERR_SETUP_DOMAIN_CONTROLLER, "Machine is a Domain Controller" },
{ WERR_LOGON_FAILURE, "Invalid logon credentials" },
{ WERR_USER_EXISTS, "User account already exists" },
+ { WERR_PASSWORD_MUST_CHANGE, "The password must be changed" },
+ { WERR_ACCOUNT_LOCKED_OUT, "Account locked out" },
+ { WERR_TIME_SKEW, "Time difference between client and server" },
};
/*****************************************************************************
diff --git a/source3/libsmb/dsgetdcname.c b/source3/libsmb/dsgetdcname.c
index 2a66d51400..bc9f4b92c8 100644
--- a/source3/libsmb/dsgetdcname.c
+++ b/source3/libsmb/dsgetdcname.c
@@ -110,7 +110,7 @@ void debug_dsdcinfo_flags(int lvl, uint32_t flags)
/*********************************************************************
********************************************************************/
-static int pack_dsdcinfo(struct DS_DOMAIN_CONTROLLER_INFO *info,
+static int pack_dsdcinfo(struct netr_DsRGetDCNameInfo *info,
unsigned char **buf)
{
unsigned char *buffer = NULL;
@@ -122,9 +122,8 @@ static int pack_dsdcinfo(struct DS_DOMAIN_CONTROLLER_INFO *info,
ZERO_STRUCT(guid_flat);
- if (info->domain_guid) {
- const struct GUID *guid = info->domain_guid;
- smb_uuid_pack(*guid, &guid_flat);
+ if (!GUID_all_zero(&info->domain_guid)) {
+ smb_uuid_pack(info->domain_guid, &guid_flat);
}
again:
@@ -132,17 +131,17 @@ static int pack_dsdcinfo(struct DS_DOMAIN_CONTROLLER_INFO *info,
if (buflen > 0) {
DEBUG(10,("pack_dsdcinfo: Packing domain %s (%s)\n",
- info->domain_name, info->domain_controller_name));
+ info->domain_name, info->dc_unc));
}
len += tdb_pack(buffer+len, buflen-len, "ffdBffdff",
- info->domain_controller_name,
- info->domain_controller_address,
- info->domain_controller_address_type,
+ info->dc_unc,
+ info->dc_address,
+ info->dc_address_type,
UUID_FLAT_SIZE, guid_flat.info,
info->domain_name,
- info->dns_forest_name,
- info->flags,
+ info->forest_name,
+ info->dc_flags,
info->dc_site_name,
info->client_site_name);
@@ -169,33 +168,33 @@ static int pack_dsdcinfo(struct DS_DOMAIN_CONTROLLER_INFO *info,
static NTSTATUS unpack_dsdcinfo(TALLOC_CTX *mem_ctx,
unsigned char *buf,
int buflen,
- struct DS_DOMAIN_CONTROLLER_INFO **info_ret)
+ struct netr_DsRGetDCNameInfo **info_ret)
{
int len = 0;
- struct DS_DOMAIN_CONTROLLER_INFO *info = NULL;
+ struct netr_DsRGetDCNameInfo *info = NULL;
uint32_t guid_len = 0;
unsigned char *guid_buf = NULL;
UUID_FLAT guid_flat;
/* forgive me 6 times */
- fstring domain_controller_name;
- fstring domain_controller_address;
+ fstring dc_unc;
+ fstring dc_address;
fstring domain_name;
- fstring dns_forest_name;
+ fstring forest_name;
fstring dc_site_name;
fstring client_site_name;
- info = TALLOC_ZERO_P(mem_ctx, struct DS_DOMAIN_CONTROLLER_INFO);
+ info = TALLOC_ZERO_P(mem_ctx, struct netr_DsRGetDCNameInfo);
NT_STATUS_HAVE_NO_MEMORY(info);
len += tdb_unpack(buf+len, buflen-len, "ffdBffdff",
- &domain_controller_name,
- &domain_controller_address,
- &info->domain_controller_address_type,
+ &dc_unc,
+ &dc_address,
+ &info->dc_address_type,
&guid_len, &guid_buf,
&domain_name,
- &dns_forest_name,
- &info->flags,
+ &forest_name,
+ &info->dc_flags,
&dc_site_name,
&client_site_name);
if (len == -1) {
@@ -203,23 +202,23 @@ static NTSTATUS unpack_dsdcinfo(TALLOC_CTX *mem_ctx,
goto failed;
}
- info->domain_controller_name =
- talloc_strdup(mem_ctx, domain_controller_name);
- info->domain_controller_address =
- talloc_strdup(mem_ctx, domain_controller_address);
+ info->dc_unc =
+ talloc_strdup(mem_ctx, dc_unc);
+ info->dc_address =
+ talloc_strdup(mem_ctx, dc_address);
info->domain_name =
talloc_strdup(mem_ctx, domain_name);
- info->dns_forest_name =
- talloc_strdup(mem_ctx, dns_forest_name);
+ info->forest_name =
+ talloc_strdup(mem_ctx, forest_name);
info->dc_site_name =
talloc_strdup(mem_ctx, dc_site_name);
info->client_site_name =
talloc_strdup(mem_ctx, client_site_name);
- if (!info->domain_controller_name ||
- !info->domain_controller_address ||
+ if (!info->dc_unc ||
+ !info->dc_address ||
!info->domain_name ||
- !info->dns_forest_name ||
+ !info->forest_name ||
!info->dc_site_name ||
!info->client_site_name) {
goto failed;
@@ -235,16 +234,12 @@ static NTSTATUS unpack_dsdcinfo(TALLOC_CTX *mem_ctx,
memcpy(&guid_flat.info, guid_buf, guid_len);
smb_uuid_unpack(guid_flat, &guid);
- info->domain_guid = (struct GUID *)talloc_memdup(
- mem_ctx, &guid, sizeof(guid));
- if (!info->domain_guid) {
- goto failed;
- }
+ info->domain_guid = guid;
SAFE_FREE(guid_buf);
}
DEBUG(10,("unpack_dcscinfo: Unpacked domain %s (%s)\n",
- info->domain_name, info->domain_controller_name));
+ info->domain_name, info->dc_unc));
*info_ret = info;
@@ -297,7 +292,7 @@ static NTSTATUS dsgetdcname_cache_delete(TALLOC_CTX *mem_ctx,
static NTSTATUS dsgetdcname_cache_store(TALLOC_CTX *mem_ctx,
const char *domain_name,
- struct DS_DOMAIN_CONTROLLER_INFO *info)
+ struct netr_DsRGetDCNameInfo *info)
{
time_t expire_time;
char *key;
@@ -346,7 +341,7 @@ static NTSTATUS dsgetdcname_cache_refresh(TALLOC_CTX *mem_ctx,
struct GUID *domain_guid,
uint32_t flags,
const char *site_name,
- struct DS_DOMAIN_CONTROLLER_INFO *info)
+ struct netr_DsRGetDCNameInfo *info)
{
struct cldap_netlogon_reply r;
@@ -355,7 +350,7 @@ static NTSTATUS dsgetdcname_cache_refresh(TALLOC_CTX *mem_ctx,
ZERO_STRUCT(r);
- if (ads_cldap_netlogon(info->domain_controller_name,
+ if (ads_cldap_netlogon(info->dc_unc,
info->domain_name, &r)) {
dsgetdcname_cache_delete(mem_ctx, domain_name);
@@ -409,7 +404,7 @@ static NTSTATUS dsgetdcname_cache_fetch(TALLOC_CTX *mem_ctx,
struct GUID *domain_guid,
uint32_t flags,
const char *site_name,
- struct DS_DOMAIN_CONTROLLER_INFO **info,
+ struct netr_DsRGetDCNameInfo **info,
bool *expired)
{
char *key;
@@ -438,13 +433,13 @@ static NTSTATUS dsgetdcname_cache_fetch(TALLOC_CTX *mem_ctx,
data_blob_free(&blob);
/* check flags */
- if (!check_cldap_reply_required_flags((*info)->flags, flags)) {
+ if (!check_cldap_reply_required_flags((*info)->dc_flags, flags)) {
DEBUG(10,("invalid flags\n"));
return NT_STATUS_INVALID_PARAMETER;
}
if ((flags & DS_IP_REQUIRED) &&
- ((*info)->domain_controller_address_type != ADS_INET_ADDRESS)) {
+ ((*info)->dc_address_type != DS_ADDRESS_TYPE_INET)) {
return NT_STATUS_INVALID_PARAMETER_MIX;
}
@@ -459,7 +454,7 @@ static NTSTATUS dsgetdcname_cached(TALLOC_CTX *mem_ctx,
struct GUID *domain_guid,
uint32_t flags,
const char *site_name,
- struct DS_DOMAIN_CONTROLLER_INFO **info)
+ struct netr_DsRGetDCNameInfo **info)
{
NTSTATUS status;
bool expired = false;
@@ -663,40 +658,36 @@ static NTSTATUS discover_dc_dns(TALLOC_CTX *mem_ctx,
****************************************************************/
static NTSTATUS make_domain_controller_info(TALLOC_CTX *mem_ctx,
- const char *domain_controller_name,
- const char *domain_controller_address,
- uint32_t domain_controller_address_type,
+ const char *dc_unc,
+ const char *dc_address,
+ uint32_t dc_address_type,
const struct GUID *domain_guid,
const char *domain_name,
- const char *dns_forest_name,
+ const char *forest_name,
uint32_t flags,
const char *dc_site_name,
const char *client_site_name,
- struct DS_DOMAIN_CONTROLLER_INFO **info_out)
+ struct netr_DsRGetDCNameInfo **info_out)
{
- struct DS_DOMAIN_CONTROLLER_INFO *info;
+ struct netr_DsRGetDCNameInfo *info;
- info = TALLOC_ZERO_P(mem_ctx, struct DS_DOMAIN_CONTROLLER_INFO);
+ info = TALLOC_ZERO_P(mem_ctx, struct netr_DsRGetDCNameInfo);
NT_STATUS_HAVE_NO_MEMORY(info);
- if (domain_controller_name) {
- info->domain_controller_name = talloc_strdup(mem_ctx,
- domain_controller_name);
- NT_STATUS_HAVE_NO_MEMORY(info->domain_controller_name);
+ if (dc_unc) {
+ info->dc_unc = talloc_strdup(mem_ctx, dc_unc);
+ NT_STATUS_HAVE_NO_MEMORY(info->dc_unc);
}
- if (domain_controller_address) {
- info->domain_controller_address = talloc_strdup(mem_ctx,
- domain_controller_address);
- NT_STATUS_HAVE_NO_MEMORY(info->domain_controller_address);
+ if (dc_address) {
+ info->dc_address = talloc_strdup(mem_ctx, dc_address);
+ NT_STATUS_HAVE_NO_MEMORY(info->dc_address);
}
- info->domain_controller_address_type = domain_controller_address_type;
+ info->dc_address_type = dc_address_type;
if (domain_guid) {
- info->domain_guid = (struct GUID *)talloc_memdup(
- mem_ctx, domain_guid, sizeof(*domain_guid));
- NT_STATUS_HAVE_NO_MEMORY(info->domain_guid);
+ info->domain_guid = *domain_guid;
}
if (domain_name) {
@@ -704,13 +695,12 @@ static NTSTATUS make_domain_controller_info(TALLOC_CTX *mem_ctx,
NT_STATUS_HAVE_NO_MEMORY(info->domain_name);
}
- if (dns_forest_name) {
- info->dns_forest_name = talloc_strdup(mem_ctx,
- dns_forest_name);
- NT_STATUS_HAVE_NO_MEMORY(info->dns_forest_name);
+ if (forest_name) {
+ info->forest_name = talloc_strdup(mem_ctx, forest_name);
+ NT_STATUS_HAVE_NO_MEMORY(info->forest_name);
}
- info->flags = flags;
+ info->dc_flags = flags;
if (dc_site_name) {
info->dc_site_name = talloc_strdup(mem_ctx, dc_site_name);
@@ -736,7 +726,7 @@ static NTSTATUS process_dc_dns(TALLOC_CTX *mem_ctx,
uint32_t flags,
struct ip_service_name **dclist,
int num_dcs,
- struct DS_DOMAIN_CONTROLLER_INFO **info)
+ struct netr_DsRGetDCNameInfo **info)
{
int i = 0;
bool valid_dc = false;
@@ -779,12 +769,12 @@ static NTSTATUS process_dc_dns(TALLOC_CTX *mem_ctx,
}
dc_hostname = r.hostname;
dc_domain_name = r.domain;
- dc_flags |= ADS_DNS_DOMAIN | ADS_DNS_CONTROLLER;
+ dc_flags |= DS_DNS_DOMAIN | DS_DNS_CONTROLLER;
} else {
/* FIXME */
dc_hostname = r.hostname;
dc_domain_name = r.domain;
- dc_flags |= ADS_DNS_DOMAIN | ADS_DNS_CONTROLLER;
+ dc_flags |= DS_DNS_DOMAIN | DS_DNS_CONTROLLER;
}
if (flags & DS_IP_REQUIRED) {
@@ -792,17 +782,17 @@ static NTSTATUS process_dc_dns(TALLOC_CTX *mem_ctx,
print_sockaddr(addr, sizeof(addr), &dclist[i]->ss);
dc_address = talloc_asprintf(mem_ctx, "\\\\%s",
addr);
- dc_address_type = ADS_INET_ADDRESS;
+ dc_address_type = DS_ADDRESS_TYPE_INET;
} else {
dc_address = talloc_asprintf(mem_ctx, "\\\\%s",
r.netbios_hostname);
- dc_address_type = ADS_NETBIOS_ADDRESS;
+ dc_address_type = DS_ADDRESS_TYPE_NETBIOS;
}
NT_STATUS_HAVE_NO_MEMORY(dc_address);
smb_uuid_unpack(r.guid, &dc_guid);
if (r.forest) {
- dc_flags |= ADS_DNS_FOREST;
+ dc_flags |= DS_DNS_FOREST;
}
return make_domain_controller_info(mem_ctx,
@@ -827,7 +817,7 @@ static NTSTATUS process_dc_netbios(TALLOC_CTX *mem_ctx,
uint32_t flags,
struct ip_service_name **dclist,
int num_dcs,
- struct DS_DOMAIN_CONTROLLER_INFO **info)
+ struct netr_DsRGetDCNameInfo **info)
{
/* FIXME: code here */
@@ -842,7 +832,7 @@ static NTSTATUS dsgetdcname_rediscover(TALLOC_CTX *mem_ctx,
struct GUID *domain_guid,
uint32_t flags,
const char *site_name,
- struct DS_DOMAIN_CONTROLLER_INFO **info)
+ struct netr_DsRGetDCNameInfo **info)
{
NTSTATUS status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
struct ip_service_name *dclist;
@@ -891,71 +881,26 @@ static NTSTATUS dsgetdcname_rediscover(TALLOC_CTX *mem_ctx,
}
/********************************************************************
-********************************************************************/
-
-NTSTATUS dsgetdcname_remote(TALLOC_CTX *mem_ctx,
- const char *computer_name,
- const char *domain_name,
- struct GUID *domain_guid,
- const char *site_name,
- uint32_t flags,
- struct DS_DOMAIN_CONTROLLER_INFO **info)
-{
- WERROR werr;
- NTSTATUS status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
- struct cli_state *cli = NULL;
- struct rpc_pipe_client *pipe_cli = NULL;
-
- status = cli_full_connection(&cli, NULL, computer_name,
- NULL, 0,
- "IPC$", "IPC",
- "",
- "",
- "",
- 0, Undefined, NULL);
-
- if (!NT_STATUS_IS_OK(status)) {
- goto done;
- }
-
- pipe_cli = cli_rpc_pipe_open_noauth(cli, PI_NETLOGON,
- &status);
- if (!pipe_cli) {
- goto done;
- }
-
- werr = rpccli_netlogon_dsr_getdcname(pipe_cli,
- mem_ctx,
- computer_name,
- domain_name,
- domain_guid,
- NULL,
- flags,
- info);
- status = werror_to_ntstatus(werr);
-
- done:
- cli_rpc_pipe_close(pipe_cli);
- if (cli) {
- cli_shutdown(cli);
- }
-
- return status;
-}
+ dsgetdcname.
-/********************************************************************
+ This will be the only public function here.
********************************************************************/
-NTSTATUS dsgetdcname_local(TALLOC_CTX *mem_ctx,
- const char *computer_name,
- const char *domain_name,
- struct GUID *domain_guid,
- const char *site_name,
- uint32_t flags,
- struct DS_DOMAIN_CONTROLLER_INFO **info)
+NTSTATUS dsgetdcname(TALLOC_CTX *mem_ctx,
+ const char *domain_name,
+ struct GUID *domain_guid,
+ const char *site_name,
+ uint32_t flags,
+ struct netr_DsRGetDCNameInfo **info)
{
NTSTATUS status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
- struct DS_DOMAIN_CONTROLLER_INFO *myinfo = NULL;
+ struct netr_DsRGetDCNameInfo *myinfo = NULL;
+
+ DEBUG(10,("dsgetdcname: domain_name: %s, "
+ "domain_guid: %s, site_name: %s, flags: 0x%08x\n",
+ domain_name,
+ domain_guid ? GUID_string(mem_ctx, domain_guid) : "(null)",
+ site_name, flags));
*info = NULL;
@@ -991,44 +936,3 @@ NTSTATUS dsgetdcname_local(TALLOC_CTX *mem_ctx,
return status;
}
-
-/********************************************************************
- dsgetdcname.
-
- This will be the only public function here.
-********************************************************************/
-
-NTSTATUS dsgetdcname(TALLOC_CTX *mem_ctx,
- const char *computer_name,
- const char *domain_name,
- struct GUID *domain_guid,
- const char *site_name,
- uint32_t flags,
- struct DS_DOMAIN_CONTROLLER_INFO **info)
-{
- DEBUG(10,("dsgetdcname: computer_name: %s, domain_name: %s, "
- "domain_guid: %s, site_name: %s, flags: 0x%08x\n",
- computer_name, domain_name,
- domain_guid ? GUID_string(mem_ctx, domain_guid) : "(null)",
- site_name, flags));
-
- *info = NULL;
-
- if (computer_name) {
- return dsgetdcname_remote(mem_ctx,
- computer_name,
- domain_name,
- domain_guid,
- site_name,
- flags,
- info);
- }
-
- return dsgetdcname_local(mem_ctx,
- computer_name,
- domain_name,
- domain_guid,
- site_name,
- flags,
- info);
-}
diff --git a/source3/libsmb/libsmb_compat.c b/source3/libsmb/libsmb_compat.c
index 573d087d6e..6042464fd2 100644
--- a/source3/libsmb/libsmb_compat.c
+++ b/source3/libsmb/libsmb_compat.c
@@ -289,6 +289,12 @@ int smbc_fstat(int fd, struct stat *st)
return (statcont->fstat)(statcont, file, st);
}
+int smbc_ftruncate(int fd, off_t size)
+{
+ SMBCFILE * file = find_fd(fd);
+ return (statcont->ftruncate)(statcont, file, size);
+}
+
int smbc_chmod(const char *url, mode_t mode)
{
return (statcont->chmod)(statcont, url, mode);
diff --git a/source3/libsmb/libsmbclient.c b/source3/libsmb/libsmbclient.c
index fb04d143a5..fe008ed6b6 100644
--- a/source3/libsmb/libsmbclient.c
+++ b/source3/libsmb/libsmbclient.c
@@ -1037,8 +1037,7 @@ smbc_attr_server(TALLOC_CTX *ctx,
const char *share,
char **pp_workgroup,
char **pp_username,
- char **pp_password,
- POLICY_HND *pol)
+ char **pp_password)
{
int flags;
struct sockaddr_storage ss;
@@ -1122,36 +1121,34 @@ smbc_attr_server(TALLOC_CTX *ctx,
ZERO_STRUCTP(ipc_srv);
ipc_srv->cli = ipc_cli;
- if (pol) {
- pipe_hnd = cli_rpc_pipe_open_noauth(ipc_srv->cli,
- PI_LSARPC,
- &nt_status);
- if (!pipe_hnd) {
- DEBUG(1, ("cli_nt_session_open fail!\n"));
- errno = ENOTSUP;
- cli_shutdown(ipc_srv->cli);
- free(ipc_srv);
- return NULL;
- }
-
- /*
- * Some systems don't support
- * SEC_RIGHTS_MAXIMUM_ALLOWED, but NT sends 0x2000000
- * so we might as well do it too.
- */
+ pipe_hnd = cli_rpc_pipe_open_noauth(ipc_srv->cli,
+ PI_LSARPC,
+ &nt_status);
+ if (!pipe_hnd) {
+ DEBUG(1, ("cli_nt_session_open fail!\n"));
+ errno = ENOTSUP;
+ cli_shutdown(ipc_srv->cli);
+ free(ipc_srv);
+ return NULL;
+ }
- nt_status = rpccli_lsa_open_policy(
- pipe_hnd,
- talloc_tos(),
- True,
- GENERIC_EXECUTE_ACCESS,
- pol);
+ /*
+ * Some systems don't support
+ * SEC_RIGHTS_MAXIMUM_ALLOWED, but NT sends 0x2000000
+ * so we might as well do it too.
+ */
- if (!NT_STATUS_IS_OK(nt_status)) {
- errno = smbc_errno(context, ipc_srv->cli);
- cli_shutdown(ipc_srv->cli);
- return NULL;
- }
+ nt_status = rpccli_lsa_open_policy(
+ pipe_hnd,
+ talloc_tos(),
+ True,
+ GENERIC_EXECUTE_ACCESS,
+ &ipc_srv->pol);
+
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ errno = smbc_errno(context, ipc_srv->cli);
+ cli_shutdown(ipc_srv->cli);
+ return NULL;
}
/* now add it to the cache (internal or external) */
@@ -2264,6 +2261,9 @@ smbc_setup_stat(SMBCCTX *context,
#ifdef HAVE_STAT_ST_BLOCKS
st->st_blocks = (size+511)/512;
#endif
+#ifdef HAVE_STRUCT_STAT_ST_RDEV
+ st->st_rdev = 0;
+#endif
st->st_uid = getuid();
st->st_gid = getgid();
@@ -2367,7 +2367,7 @@ smbc_stat_ctx(SMBCCTX *context,
st->st_ino = ino;
- smbc_setup_stat(context, st, path, size, mode);
+ smbc_setup_stat(context, st, (char *) fname, size, mode);
set_atimespec(st, access_time_ts);
set_ctimespec(st, change_time_ts);
@@ -2483,6 +2483,80 @@ smbc_fstat_ctx(SMBCCTX *context,
}
/*
+ * Routine to truncate a file given by its file descriptor, to a specified size
+ */
+
+static int
+smbc_ftruncate_ctx(SMBCCTX *context,
+ SMBCFILE *file,
+ off_t length)
+{
+ SMB_OFF_T size = length;
+ char *server = NULL;
+ char *share = NULL;
+ char *user = NULL;
+ char *password = NULL;
+ char *path = NULL;
+ char *targetpath = NULL;
+ struct cli_state *targetcli = NULL;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ if (!context || !context->internal ||
+ !context->internal->_initialized) {
+ errno = EINVAL;
+ TALLOC_FREE(frame);
+ return -1;
+ }
+
+ if (!file || !DLIST_CONTAINS(context->internal->_files, file)) {
+ errno = EBADF;
+ TALLOC_FREE(frame);
+ return -1;
+ }
+
+ if (!file->file) {
+ errno = EINVAL;
+ TALLOC_FREE(frame);
+ return -1;
+ }
+
+ /*d_printf(">>>fstat: parsing %s\n", file->fname);*/
+ if (smbc_parse_path(frame,
+ context,
+ file->fname,
+ NULL,
+ &server,
+ &share,
+ &path,
+ &user,
+ &password,
+ NULL)) {
+ errno = EINVAL;
+ TALLOC_FREE(frame);
+ return -1;
+ }
+
+ /*d_printf(">>>fstat: resolving %s\n", path);*/
+ if (!cli_resolve_path(frame, "", file->srv->cli, path,
+ &targetcli, &targetpath)) {
+ d_printf("Could not resolve %s\n", path);
+ TALLOC_FREE(frame);
+ return -1;
+ }
+ /*d_printf(">>>fstat: resolved path as %s\n", targetpath);*/
+
+ if (!cli_ftruncate(targetcli, file->cli_fd, size)) {
+ errno = EINVAL;
+ TALLOC_FREE(frame);
+ return -1;
+ }
+
+ TALLOC_FREE(frame);
+ return 0;
+
+}
+
+/*
* Routine to open a directory
* We accept the URL syntax explained in smbc_parse_path(), above.
*/
@@ -4689,7 +4763,15 @@ dos_attr_parse(SMBCCTX *context,
frame = talloc_stackframe();
while (next_token_talloc(frame, &p, &tok, "\t,\r\n")) {
if (StrnCaseCmp(tok, "MODE:", 5) == 0) {
- dad->mode = strtol(tok+5, NULL, 16);
+ long request = strtol(tok+5, NULL, 16);
+ if (request == 0) {
+ dad->mode = (request |
+ (IS_DOS_DIR(dad->mode)
+ ? FILE_ATTRIBUTE_DIRECTORY
+ : FILE_ATTRIBUTE_NORMAL));
+ } else {
+ dad->mode = request;
+ }
continue;
}
@@ -5725,7 +5807,6 @@ smbc_setxattr_ctx(SMBCCTX *context,
char *password = NULL;
char *workgroup = NULL;
char *path = NULL;
- POLICY_HND pol;
DOS_ATTR_DESC *dad = NULL;
struct {
const char * create_time_attr;
@@ -5784,8 +5865,7 @@ smbc_setxattr_ctx(SMBCCTX *context,
if (! srv->no_nt_session) {
ipc_srv = smbc_attr_server(frame, context, server, share,
- &workgroup, &user, &password,
- &pol);
+ &workgroup, &user, &password);
if (! ipc_srv) {
srv->no_nt_session = True;
}
@@ -5811,7 +5891,7 @@ smbc_setxattr_ctx(SMBCCTX *context,
if (ipc_srv) {
ret = cacl_set(talloc_tos(), srv->cli,
- ipc_srv->cli, &pol, path,
+ ipc_srv->cli, &ipc_srv->pol, path,
namevalue,
(*namevalue == '*'
? SMBC_XATTR_MODE_SET
@@ -5875,7 +5955,7 @@ smbc_setxattr_ctx(SMBCCTX *context,
ret = -1;
} else {
ret = cacl_set(talloc_tos(), srv->cli,
- ipc_srv->cli, &pol, path,
+ ipc_srv->cli, &ipc_srv->pol, path,
namevalue,
(*namevalue == '*'
? SMBC_XATTR_MODE_SET
@@ -5905,7 +5985,7 @@ smbc_setxattr_ctx(SMBCCTX *context,
ret = -1;
} else {
ret = cacl_set(talloc_tos(), srv->cli,
- ipc_srv->cli, &pol, path,
+ ipc_srv->cli, &ipc_srv->pol, path,
namevalue, SMBC_XATTR_MODE_CHOWN, 0);
}
TALLOC_FREE(frame);
@@ -5932,8 +6012,8 @@ smbc_setxattr_ctx(SMBCCTX *context,
ret = -1;
} else {
ret = cacl_set(talloc_tos(), srv->cli,
- ipc_srv->cli, &pol, path,
- namevalue, SMBC_XATTR_MODE_CHOWN, 0);
+ ipc_srv->cli, &ipc_srv->pol, path,
+ namevalue, SMBC_XATTR_MODE_CHGRP, 0);
}
TALLOC_FREE(frame);
return ret;
@@ -6023,7 +6103,6 @@ smbc_getxattr_ctx(SMBCCTX *context,
char *password = NULL;
char *workgroup = NULL;
char *path = NULL;
- POLICY_HND pol;
struct {
const char * create_time_attr;
const char * access_time_attr;
@@ -6080,8 +6159,7 @@ smbc_getxattr_ctx(SMBCCTX *context,
if (! srv->no_nt_session) {
ipc_srv = smbc_attr_server(frame, context, server, share,
- &workgroup, &user, &password,
- &pol);
+ &workgroup, &user, &password);
if (! ipc_srv) {
srv->no_nt_session = True;
}
@@ -6134,7 +6212,7 @@ smbc_getxattr_ctx(SMBCCTX *context,
/* Yup. */
ret = cacl_get(context, talloc_tos(), srv,
ipc_srv == NULL ? NULL : ipc_srv->cli,
- &pol, path,
+ &ipc_srv->pol, path,
CONST_DISCARD(char *, name),
CONST_DISCARD(char *, value), size);
if (ret < 0 && errno == 0) {
@@ -6165,7 +6243,6 @@ smbc_removexattr_ctx(SMBCCTX *context,
char *password = NULL;
char *workgroup = NULL;
char *path = NULL;
- POLICY_HND pol;
TALLOC_CTX *frame = talloc_stackframe();
if (!context || !context->internal ||
@@ -6216,8 +6293,7 @@ smbc_removexattr_ctx(SMBCCTX *context,
if (! srv->no_nt_session) {
ipc_srv = smbc_attr_server(frame, context, server, share,
- &workgroup, &user, &password,
- &pol);
+ &workgroup, &user, &password);
if (! ipc_srv) {
srv->no_nt_session = True;
}
@@ -6236,7 +6312,7 @@ smbc_removexattr_ctx(SMBCCTX *context,
/* Yup. */
ret = cacl_set(talloc_tos(), srv->cli,
- ipc_srv->cli, &pol, path,
+ ipc_srv->cli, &ipc_srv->pol, path,
NULL, SMBC_XATTR_MODE_REMOVE_ALL, 0);
TALLOC_FREE(frame);
return ret;
@@ -6256,7 +6332,7 @@ smbc_removexattr_ctx(SMBCCTX *context,
/* Yup. */
ret = cacl_set(talloc_tos(), srv->cli,
- ipc_srv->cli, &pol, path,
+ ipc_srv->cli, &ipc_srv->pol, path,
name + 19, SMBC_XATTR_MODE_REMOVE, 0);
TALLOC_FREE(frame);
return ret;
@@ -6701,6 +6777,7 @@ smbc_new_context(void)
context->telldir = smbc_telldir_ctx;
context->lseekdir = smbc_lseekdir_ctx;
context->fstatdir = smbc_fstatdir_ctx;
+ context->ftruncate = smbc_ftruncate_ctx;
context->chmod = smbc_chmod_ctx;
context->utimes = smbc_utimes_ctx;
context->setxattr = smbc_setxattr_ctx;
@@ -6795,7 +6872,7 @@ smbc_free_context(SMBCCTX *context,
SAFE_FREE(context->netbios_name);
SAFE_FREE(context->user);
- DEBUG(3, ("Context %p succesfully freed\n", context));
+ DEBUG(3, ("Context %p successfully freed\n", context));
SAFE_FREE(context->internal);
SAFE_FREE(context);
return 0;
diff --git a/source3/libsmb/namequery.c b/source3/libsmb/namequery.c
index ad999b34b4..ad16452e3e 100644
--- a/source3/libsmb/namequery.c
+++ b/source3/libsmb/namequery.c
@@ -1299,11 +1299,11 @@ static NTSTATUS resolve_hosts(const char *name, int name_type,
Resolve via "ADS" method.
*********************************************************/
-NTSTATUS resolve_ads(const char *name,
- int name_type,
- const char *sitename,
- struct ip_service **return_iplist,
- int *return_count)
+static NTSTATUS resolve_ads(const char *name,
+ int name_type,
+ const char *sitename,
+ struct ip_service **return_iplist,
+ int *return_count)
{
int i, j;
NTSTATUS status;
diff --git a/source3/libsmb/ntlmssp_parse.c b/source3/libsmb/ntlmssp_parse.c
index ac8846ad1e..70377cba7d 100644
--- a/source3/libsmb/ntlmssp_parse.c
+++ b/source3/libsmb/ntlmssp_parse.c
@@ -170,6 +170,7 @@ bool msrpc_gen(DATA_BLOB *blob,
/* a helpful macro to avoid running over the end of our blob */
#define NEED_DATA(amount) \
if ((head_ofs + amount) > blob->length) { \
+ va_end(ap); \
return False; \
}
@@ -216,16 +217,20 @@ bool msrpc_parse(const DATA_BLOB *blob,
if ((len1 != len2) || (ptr + len1 < ptr) ||
(ptr + len1 < len1) ||
(ptr + len1 > blob->length)) {
+ va_end(ap);
return false;
}
if (len1 & 1) {
/* if odd length and unicode */
+ va_end(ap);
return false;
}
if (blob->data + ptr <
(uint8 *)(unsigned long)ptr ||
- blob->data + ptr < blob->data)
+ blob->data + ptr < blob->data) {
+ va_end(ap);
return false;
+ }
if (0 < len1) {
char *p = NULL;
@@ -261,13 +266,16 @@ bool msrpc_parse(const DATA_BLOB *blob,
if ((len1 != len2) || (ptr + len1 < ptr) ||
(ptr + len1 < len1) ||
(ptr + len1 > blob->length)) {
+ va_end(ap);
return false;
}
if (blob->data + ptr <
(uint8 *)(unsigned long)ptr ||
- blob->data + ptr < blob->data)
+ blob->data + ptr < blob->data) {
+ va_end(ap);
return false;
+ }
if (0 < len1) {
char *p = NULL;
@@ -304,13 +312,16 @@ bool msrpc_parse(const DATA_BLOB *blob,
if ((len1 != len2) || (ptr + len1 < ptr) ||
(ptr + len1 < len1) ||
(ptr + len1 > blob->length)) {
+ va_end(ap);
return false;
}
if (blob->data + ptr <
(uint8 *)(unsigned long)ptr ||
- blob->data + ptr < blob->data)
+ blob->data + ptr < blob->data) {
+ va_end(ap);
return false;
+ }
*b = data_blob(blob->data + ptr, len1);
}
@@ -322,6 +333,7 @@ bool msrpc_parse(const DATA_BLOB *blob,
NEED_DATA(len1);
if (blob->data + head_ofs < (uint8 *)head_ofs ||
blob->data + head_ofs < blob->data) {
+ va_end(ap);
return false;
}
@@ -337,7 +349,8 @@ bool msrpc_parse(const DATA_BLOB *blob,
s = va_arg(ap, char *);
if (blob->data + head_ofs < (uint8 *)head_ofs ||
- blob->data + head_ofs < blob->data) {
+ blob->data + head_ofs < blob->data) {
+ va_end(ap);
return false;
}
@@ -351,11 +364,13 @@ bool msrpc_parse(const DATA_BLOB *blob,
blob->length - head_ofs,
STR_ASCII|STR_TERMINATE);
if (ret == (size_t)-1 || p == NULL) {
+ va_end(ap);
return false;
}
head_ofs += ret;
if (strcmp(s, p) != 0) {
TALLOC_FREE(p);
+ va_end(ap);
return false;
}
TALLOC_FREE(p);
diff --git a/source3/libsmb/samlogon_cache.c b/source3/libsmb/samlogon_cache.c
index 4f791f66f6..73b570c383 100644
--- a/source3/libsmb/samlogon_cache.c
+++ b/source3/libsmb/samlogon_cache.c
@@ -1,21 +1,22 @@
-/*
+/*
Unix SMB/CIFS implementation.
Net_sam_logon info3 helpers
Copyright (C) Alexander Bokovoy 2002.
Copyright (C) Andrew Bartlett 2002.
Copyright (C) Gerald Carter 2003.
Copyright (C) Tim Potter 2003.
-
+ Copyright (C) Guenther Deschner 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 <http://www.gnu.org/licenses/>.
*/
@@ -29,12 +30,12 @@ static TDB_CONTEXT *netsamlogon_tdb = NULL;
/***********************************************************************
open the tdb
***********************************************************************/
-
+
bool netsamlogon_cache_init(void)
{
if (!netsamlogon_tdb) {
netsamlogon_tdb = tdb_open_log(lock_path(NETSAMLOGON_TDB), 0,
- TDB_DEFAULT, O_RDWR | O_CREAT, 0600);
+ TDB_DEFAULT, O_RDWR | O_CREAT, 0600);
}
return (netsamlogon_tdb != NULL);
@@ -47,37 +48,39 @@ bool netsamlogon_cache_init(void)
bool netsamlogon_cache_shutdown(void)
{
- if(netsamlogon_tdb)
+ if (netsamlogon_tdb) {
return (tdb_close(netsamlogon_tdb) == 0);
-
- return True;
+ }
+
+ return true;
}
/***********************************************************************
Clear cache getpwnam and getgroups entries from the winbindd cache
***********************************************************************/
-void netsamlogon_clear_cached_user(TDB_CONTEXT *tdb, NET_USER_INFO_3 *user)
+
+void netsamlogon_clear_cached_user(TDB_CONTEXT *tdb, struct netr_SamInfo3 *info3)
{
- bool got_tdb = False;
+ bool got_tdb = false;
DOM_SID sid;
fstring key_str, sid_string;
/* We may need to call this function from smbd which will not have
- winbindd_cache.tdb open. Open the tdb if a NULL is passed. */
+ winbindd_cache.tdb open. Open the tdb if a NULL is passed. */
if (!tdb) {
- tdb = tdb_open_log(lock_path("winbindd_cache.tdb"),
+ tdb = tdb_open_log(lock_path("winbindd_cache.tdb"),
WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
TDB_DEFAULT, O_RDWR, 0600);
if (!tdb) {
DEBUG(5, ("netsamlogon_clear_cached_user: failed to open cache\n"));
return;
}
- got_tdb = True;
+ got_tdb = true;
}
- sid_copy(&sid, &user->dom_sid.sid);
- sid_append_rid(&sid, user->user_rid);
+ sid_copy(&sid, info3->base.domain_sid);
+ sid_append_rid(&sid, info3->base.rid);
/* Clear U/SID cache entry */
@@ -95,157 +98,178 @@ void netsamlogon_clear_cached_user(TDB_CONTEXT *tdb, NET_USER_INFO_3 *user)
tdb_delete(tdb, string_tdb_data(key_str));
- if (got_tdb)
+ if (got_tdb) {
tdb_close(tdb);
+ }
}
/***********************************************************************
- Store a NET_USER_INFO_3 structure in a tdb for later user
+ Store a netr_SamInfo3 structure in a tdb for later user
username should be in UTF-8 format
***********************************************************************/
-bool netsamlogon_cache_store( const char *username, NET_USER_INFO_3 *user )
+bool netsamlogon_cache_store(const char *username, struct netr_SamInfo3 *info3)
{
- TDB_DATA data;
- fstring keystr, tmp;
- prs_struct ps;
- bool result = False;
- DOM_SID user_sid;
- time_t t = time(NULL);
- TALLOC_CTX *mem_ctx;
-
+ TDB_DATA data;
+ fstring keystr, tmp;
+ bool result = false;
+ DOM_SID user_sid;
+ time_t t = time(NULL);
+ TALLOC_CTX *mem_ctx;
+ DATA_BLOB blob;
+ enum ndr_err_code ndr_err;
+ struct netsamlogoncache_entry r;
+
+ if (!info3) {
+ return false;
+ }
if (!netsamlogon_cache_init()) {
- DEBUG(0,("netsamlogon_cache_store: cannot open %s for write!\n", NETSAMLOGON_TDB));
- return False;
+ DEBUG(0,("netsamlogon_cache_store: cannot open %s for write!\n",
+ NETSAMLOGON_TDB));
+ return false;
}
- sid_copy( &user_sid, &user->dom_sid.sid );
- sid_append_rid( &user_sid, user->user_rid );
+ sid_copy(&user_sid, info3->base.domain_sid);
+ sid_append_rid(&user_sid, info3->base.rid);
/* Prepare key as DOMAIN-SID/USER-RID string */
slprintf(keystr, sizeof(keystr), "%s", sid_to_fstring(tmp, &user_sid));
DEBUG(10,("netsamlogon_cache_store: SID [%s]\n", keystr));
-
+
+ /* Prepare data */
+
+ if (!(mem_ctx = TALLOC_P( NULL, int))) {
+ DEBUG(0,("netsamlogon_cache_store: talloc() failed!\n"));
+ return false;
+ }
+
/* only Samba fills in the username, not sure why NT doesn't */
/* so we fill it in since winbindd_getpwnam() makes use of it */
-
- if ( !user->uni_user_name.buffer ) {
- init_unistr2( &user->uni_user_name, username, UNI_STR_TERMINATE );
- init_uni_hdr( &user->hdr_user_name, &user->uni_user_name );
+
+ if (!info3->base.account_name.string) {
+ info3->base.account_name.string = talloc_strdup(mem_ctx, username);
}
-
- /* Prepare data */
-
- if ( !(mem_ctx = TALLOC_P( NULL, int )) ) {
- DEBUG(0,("netsamlogon_cache_store: talloc() failed!\n"));
- return False;
+
+ r.timestamp = t;
+ r.info3 = *info3;
+
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_DEBUG(netsamlogoncache_entry, &r);
}
- prs_init( &ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-
- {
- uint32 ts = (uint32)t;
- if ( !prs_uint32( "timestamp", &ps, 0, &ts ) )
- return False;
+ ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &r,
+ (ndr_push_flags_fn_t)ndr_push_netsamlogoncache_entry);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ DEBUG(0,("netsamlogon_cache_store: failed to push entry to cache\n"));
+ TALLOC_FREE(mem_ctx);
+ return false;
}
-
- if ( net_io_user_info3("", user, &ps, 0, 3, 0) )
- {
- data.dsize = prs_offset( &ps );
- data.dptr = (uint8 *)prs_data_p( &ps );
- if (tdb_store_bystring(netsamlogon_tdb, keystr, data, TDB_REPLACE) != -1)
- result = True;
-
- prs_mem_free( &ps );
+ data.dsize = blob.length;
+ data.dptr = blob.data;
+
+ if (tdb_store_bystring(netsamlogon_tdb, keystr, data, TDB_REPLACE) != -1) {
+ result = true;
}
- TALLOC_FREE( mem_ctx );
-
+ TALLOC_FREE(mem_ctx);
+
return result;
}
/***********************************************************************
- Retrieves a NET_USER_INFO_3 structure from a tdb. Caller must
+ Retrieves a netr_SamInfo3 structure from a tdb. Caller must
free the user_info struct (malloc()'d memory)
***********************************************************************/
-NET_USER_INFO_3* netsamlogon_cache_get( TALLOC_CTX *mem_ctx, const DOM_SID *user_sid)
+struct netr_SamInfo3 *netsamlogon_cache_get(TALLOC_CTX *mem_ctx, const DOM_SID *user_sid)
{
- NET_USER_INFO_3 *user = NULL;
- TDB_DATA data;
- prs_struct ps;
- fstring keystr, tmp;
- uint32 t;
-
+ struct netr_SamInfo3 *info3 = NULL;
+ TDB_DATA data;
+ fstring keystr, tmp;
+ enum ndr_err_code ndr_err;
+ DATA_BLOB blob;
+ struct netsamlogoncache_entry r;
+
if (!netsamlogon_cache_init()) {
- DEBUG(0,("netsamlogon_cache_get: cannot open %s for write!\n", NETSAMLOGON_TDB));
- return False;
+ DEBUG(0,("netsamlogon_cache_get: cannot open %s for write!\n",
+ NETSAMLOGON_TDB));
+ return false;
}
/* Prepare key as DOMAIN-SID/USER-RID string */
slprintf(keystr, sizeof(keystr), "%s", sid_to_fstring(tmp, user_sid));
DEBUG(10,("netsamlogon_cache_get: SID [%s]\n", keystr));
data = tdb_fetch_bystring( netsamlogon_tdb, keystr );
-
- if ( data.dptr ) {
- user = TALLOC_ZERO_P(mem_ctx, NET_USER_INFO_3);
- if (user == NULL) {
- return NULL;
- }
+ if (!data.dptr) {
+ return NULL;
+ }
- prs_init( &ps, 0, mem_ctx, UNMARSHALL );
- prs_give_memory( &ps, (char *)data.dptr, data.dsize, True );
-
- if ( !prs_uint32( "timestamp", &ps, 0, &t ) ) {
- prs_mem_free( &ps );
- TALLOC_FREE(user);
- return False;
- }
-
- if ( !net_io_user_info3("", user, &ps, 0, 3, 0) ) {
- TALLOC_FREE( user );
- }
-
- prs_mem_free( &ps );
+ info3 = TALLOC_ZERO_P(mem_ctx, struct netr_SamInfo3);
+ if (!info3) {
+ goto done;
+ }
+
+ blob.data = (uint8 *)data.dptr;
+ blob.length = data.dsize;
+
+ ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
+ (ndr_pull_flags_fn_t)ndr_pull_netsamlogoncache_entry);
-#if 0 /* The netsamlogon cache needs to hang around. Something about
+ if (DEBUGLEVEL >= 10) {
+ NDR_PRINT_DEBUG(netsamlogoncache_entry, &r);
+ }
+
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ DEBUG(0,("netsamlogon_cache_get: failed to pull entry from cache\n"));
+ tdb_delete(netsamlogon_tdb, data);
+ TALLOC_FREE(info3);
+ goto done;
+ }
+
+ info3 = (struct netr_SamInfo3 *)talloc_memdup(mem_ctx, &r.info3,
+ sizeof(r.info3));
+
+ done:
+ SAFE_FREE(data.dptr);
+
+ return info3;
+
+#if 0 /* The netsamlogon cache needs to hang around. Something about
this feels wrong, but it is the only way we can get all of the
groups. The old universal groups cache didn't expire either.
--jerry */
{
time_t now = time(NULL);
uint32 time_diff;
-
+
/* is the entry expired? */
time_diff = now - t;
-
+
if ( (time_diff < 0 ) || (time_diff > lp_winbind_cache_time()) ) {
DEBUG(10,("netsamlogon_cache_get: cache entry expired \n"));
tdb_delete( netsamlogon_tdb, key );
TALLOC_FREE( user );
}
-#endif
}
-
- return user;
+#endif
}
bool netsamlogon_cache_have(const DOM_SID *user_sid)
{
TALLOC_CTX *mem_ctx = talloc_init("netsamlogon_cache_have");
- NET_USER_INFO_3 *user = NULL;
+ struct netr_SamInfo3 *info3 = NULL;
bool result;
if (!mem_ctx)
return False;
- user = netsamlogon_cache_get(mem_ctx, user_sid);
+ info3 = netsamlogon_cache_get(mem_ctx, user_sid);
- result = (user != NULL);
+ result = (info3 != NULL);
talloc_destroy(mem_ctx);
diff --git a/source3/libsmb/smb_seal.c b/source3/libsmb/smb_seal.c
index b5befbf7cd..a81ae9afd5 100644
--- a/source3/libsmb/smb_seal.c
+++ b/source3/libsmb/smb_seal.c
@@ -483,15 +483,15 @@ NTSTATUS cli_decrypt_message(struct cli_state *cli)
Encrypt an outgoing buffer. Return the encrypted pointer in buf_out.
******************************************************************************/
-NTSTATUS cli_encrypt_message(struct cli_state *cli, char **buf_out)
+NTSTATUS cli_encrypt_message(struct cli_state *cli, char *buf, char **buf_out)
{
/* Ignore non-session messages. */
- if(CVAL(cli->outbuf,0)) {
+ if (CVAL(buf,0)) {
return NT_STATUS_OK;
}
/* If we supported multiple encrytion contexts
* here we'd look up based on tid.
*/
- return common_encrypt_buffer(cli->trans_enc_state, cli->outbuf, buf_out);
+ return common_encrypt_buffer(cli->trans_enc_state, buf, buf_out);
}
diff --git a/source3/libsmb/smb_signing.c b/source3/libsmb/smb_signing.c
index f03c21bd0e..bd6d97123d 100644
--- a/source3/libsmb/smb_signing.c
+++ b/source3/libsmb/smb_signing.c
@@ -573,9 +573,9 @@ void cli_free_signing_context(struct cli_state *cli)
* Sign a packet with the current mechanism
*/
-void cli_calculate_sign_mac(struct cli_state *cli)
+void cli_calculate_sign_mac(struct cli_state *cli, char *buf)
{
- cli->sign_info.sign_outgoing_message(cli->outbuf, &cli->sign_info);
+ cli->sign_info.sign_outgoing_message(buf, &cli->sign_info);
}
/**
@@ -584,9 +584,9 @@ void cli_calculate_sign_mac(struct cli_state *cli)
* which had a bad checksum, True otherwise.
*/
-bool cli_check_sign_mac(struct cli_state *cli)
+bool cli_check_sign_mac(struct cli_state *cli, char *buf)
{
- if (!cli->sign_info.check_incoming_message(cli->inbuf, &cli->sign_info, True)) {
+ if (!cli->sign_info.check_incoming_message(buf, &cli->sign_info, True)) {
free_signing_context(&cli->sign_info);
return False;
}
diff --git a/source3/libsmb/trusts_util.c b/source3/libsmb/trusts_util.c
index 732dc78c75..c079fb149a 100644
--- a/source3/libsmb/trusts_util.c
+++ b/source3/libsmb/trusts_util.c
@@ -40,7 +40,7 @@ static NTSTATUS just_change_the_password(struct rpc_pipe_client *cli, TALLOC_CTX
already have valid creds. If not we must set them up. */
if (cli->auth.auth_type != PIPE_AUTH_TYPE_SCHANNEL) {
- uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
+ uint32 neg_flags = NETLOGON_NEG_SELECT_AUTH2_FLAGS;
result = rpccli_netlogon_setup_creds(cli,
cli->cli->desthost, /* server name */
@@ -58,7 +58,32 @@ static NTSTATUS just_change_the_password(struct rpc_pipe_client *cli, TALLOC_CTX
}
}
- result = rpccli_net_srv_pwset(cli, mem_ctx, global_myname(), new_trust_passwd_hash);
+ {
+ struct netr_Authenticator clnt_creds, srv_cred;
+ struct samr_Password new_password;
+
+ netlogon_creds_client_step(cli->dc, &clnt_creds);
+
+ cred_hash3(new_password.hash,
+ new_trust_passwd_hash,
+ cli->dc->sess_key, 1);
+
+ result = rpccli_netr_ServerPasswordSet(cli, mem_ctx,
+ cli->dc->remote_machine,
+ cli->dc->mach_acct,
+ sec_channel_type,
+ global_myname(),
+ &clnt_creds,
+ &srv_cred,
+ &new_password);
+
+ /* Always check returned credentials. */
+ if (!netlogon_creds_client_check(cli->dc, &srv_cred.cred)) {
+ DEBUG(0,("rpccli_netr_ServerPasswordSet: "
+ "credentials chain check failed\n"));
+ return NT_STATUS_ACCESS_DENIED;
+ }
+ }
if (!NT_STATUS_IS_OK(result)) {
DEBUG(0,("just_change_the_password: unable to change password (%s)!\n",
@@ -152,6 +177,8 @@ bool enumerate_domain_trusts( TALLOC_CTX *mem_ctx, const char *domain,
struct cli_state *cli = NULL;
struct rpc_pipe_client *lsa_pipe;
bool retry;
+ struct lsa_DomainList dom_list;
+ int i;
*domain_names = NULL;
*num_domains = 0;
@@ -182,17 +209,39 @@ bool enumerate_domain_trusts( TALLOC_CTX *mem_ctx, const char *domain,
/* get a handle */
result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, True,
- POLICY_VIEW_LOCAL_INFORMATION, &pol);
+ LSA_POLICY_VIEW_LOCAL_INFORMATION, &pol);
if ( !NT_STATUS_IS_OK(result) )
goto done;
/* Lookup list of trusted domains */
- result = rpccli_lsa_enum_trust_dom(lsa_pipe, mem_ctx, &pol, &enum_ctx,
- num_domains, domain_names, sids);
+ result = rpccli_lsa_EnumTrustDom(lsa_pipe, mem_ctx,
+ &pol,
+ &enum_ctx,
+ &dom_list,
+ (uint32_t)-1);
if ( !NT_STATUS_IS_OK(result) )
goto done;
+ *num_domains = dom_list.count;
+
+ *domain_names = TALLOC_ZERO_ARRAY(mem_ctx, char *, *num_domains);
+ if (!*domain_names) {
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ *sids = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, *num_domains);
+ if (!*sids) {
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ for (i=0; i< *num_domains; i++) {
+ (*domain_names)[i] = CONST_DISCARD(char *, dom_list.domains[i].name.string);
+ (*sids)[i] = *dom_list.domains[i].sid;
+ }
+
done:
/* cleanup */
if (cli) {