summaryrefslogtreecommitdiff
path: root/source3/libsmb
diff options
context:
space:
mode:
authorNadezhda Ivanova <nadezhda.ivanova@postpath.com>2010-01-04 11:24:10 +0200
committerNadezhda Ivanova <nadezhda.ivanova@postpath.com>2010-01-04 11:24:10 +0200
commitfb5383c69ee52fb5e6d066a43451dc8c806cc795 (patch)
tree45b72e03f68ab6d212755c524f8e8a60a3b4373a /source3/libsmb
parent60d8ab3b7b0bd2c9b633f0380d1fdf5bcf5e2621 (diff)
parenta06e5cdb99ddf7abf16486d3837105ec4e0da9ee (diff)
downloadsamba-fb5383c69ee52fb5e6d066a43451dc8c806cc795.tar.gz
samba-fb5383c69ee52fb5e6d066a43451dc8c806cc795.tar.bz2
samba-fb5383c69ee52fb5e6d066a43451dc8c806cc795.zip
Merge branch 'master' of git://git.samba.org/samba
Diffstat (limited to 'source3/libsmb')
-rw-r--r--source3/libsmb/async_smb.c219
-rw-r--r--source3/libsmb/cliconnect.c943
-rw-r--r--source3/libsmb/clidfs.c6
-rw-r--r--source3/libsmb/clifsinfo.c1
-rw-r--r--source3/libsmb/conncache.c82
-rw-r--r--source3/libsmb/errormap.c6
-rw-r--r--source3/libsmb/libsmb_cache.c4
-rw-r--r--source3/libsmb/ntlmssp.c88
-rw-r--r--source3/libsmb/ntlmssp_ndr.c145
-rw-r--r--source3/libsmb/ntlmssp_ndr.h44
-rw-r--r--source3/libsmb/ntlmssp_sign.c53
-rw-r--r--source3/libsmb/smb_seal.c5
12 files changed, 767 insertions, 829 deletions
diff --git a/source3/libsmb/async_smb.c b/source3/libsmb/async_smb.c
index 6edfe514b8..f5000e4730 100644
--- a/source3/libsmb/async_smb.c
+++ b/source3/libsmb/async_smb.c
@@ -153,180 +153,6 @@ void cli_set_error(struct cli_state *cli, NTSTATUS status)
}
/**
- * @brief Find the smb_cmd offset of the last command pushed
- * @param[in] buf The buffer we're building up
- * @retval Where can we put our next andx cmd?
- *
- * While chaining requests, the "next" request we're looking at needs to put
- * its SMB_Command before the data the previous request already built up added
- * to the chain. Find the offset to the place where we have to put our cmd.
- */
-
-static bool find_andx_cmd_ofs(uint8_t *buf, size_t *pofs)
-{
- uint8_t cmd;
- size_t ofs;
-
- cmd = CVAL(buf, smb_com);
-
- SMB_ASSERT(is_andx_req(cmd));
-
- ofs = smb_vwv0;
-
- while (CVAL(buf, ofs) != 0xff) {
-
- if (!is_andx_req(CVAL(buf, ofs))) {
- return false;
- }
-
- /*
- * ofs is from start of smb header, so add the 4 length
- * bytes. The next cmd is right after the wct field.
- */
- ofs = SVAL(buf, ofs+2) + 4 + 1;
-
- SMB_ASSERT(ofs+4 < talloc_get_size(buf));
- }
-
- *pofs = ofs;
- return true;
-}
-
-/**
- * @brief Do the smb chaining at a buffer level
- * @param[in] poutbuf Pointer to the talloc'ed buffer to be modified
- * @param[in] smb_command The command that we want to issue
- * @param[in] wct How many words?
- * @param[in] vwv The words, already in network order
- * @param[in] bytes_alignment How shall we align "bytes"?
- * @param[in] num_bytes How many bytes?
- * @param[in] bytes The data the request ships
- *
- * smb_splice_chain() adds the vwv and bytes to the request already present in
- * *poutbuf.
- */
-
-bool smb_splice_chain(uint8_t **poutbuf, uint8_t smb_command,
- uint8_t wct, const uint16_t *vwv,
- size_t bytes_alignment,
- uint32_t num_bytes, const uint8_t *bytes)
-{
- uint8_t *outbuf;
- size_t old_size, new_size;
- size_t ofs;
- size_t chain_padding = 0;
- size_t bytes_padding = 0;
- bool first_request;
-
- old_size = talloc_get_size(*poutbuf);
-
- /*
- * old_size == smb_wct means we're pushing the first request in for
- * libsmb/
- */
-
- first_request = (old_size == smb_wct);
-
- if (!first_request && ((old_size % 4) != 0)) {
- /*
- * Align the wct field of subsequent requests to a 4-byte
- * boundary
- */
- chain_padding = 4 - (old_size % 4);
- }
-
- /*
- * After the old request comes the new wct field (1 byte), the vwv's
- * and the num_bytes field. After at we might need to align the bytes
- * given to us to "bytes_alignment", increasing the num_bytes value.
- */
-
- new_size = old_size + chain_padding + 1 + wct * sizeof(uint16_t) + 2;
-
- if ((bytes_alignment != 0) && ((new_size % bytes_alignment) != 0)) {
- bytes_padding = bytes_alignment - (new_size % bytes_alignment);
- }
-
- new_size += bytes_padding + num_bytes;
-
- if ((smb_command != SMBwriteX) && (new_size > 0xffff)) {
- DEBUG(1, ("splice_chain: %u bytes won't fit\n",
- (unsigned)new_size));
- return false;
- }
-
- outbuf = TALLOC_REALLOC_ARRAY(NULL, *poutbuf, uint8_t, new_size);
- if (outbuf == NULL) {
- DEBUG(0, ("talloc failed\n"));
- return false;
- }
- *poutbuf = outbuf;
-
- if (first_request) {
- SCVAL(outbuf, smb_com, smb_command);
- } else {
- size_t andx_cmd_ofs;
-
- if (!find_andx_cmd_ofs(outbuf, &andx_cmd_ofs)) {
- DEBUG(1, ("invalid command chain\n"));
- *poutbuf = TALLOC_REALLOC_ARRAY(
- NULL, *poutbuf, uint8_t, old_size);
- return false;
- }
-
- if (chain_padding != 0) {
- memset(outbuf + old_size, 0, chain_padding);
- old_size += chain_padding;
- }
-
- SCVAL(outbuf, andx_cmd_ofs, smb_command);
- SSVAL(outbuf, andx_cmd_ofs + 2, old_size - 4);
- }
-
- ofs = old_size;
-
- /*
- * Push the chained request:
- *
- * wct field
- */
-
- SCVAL(outbuf, ofs, wct);
- ofs += 1;
-
- /*
- * vwv array
- */
-
- memcpy(outbuf + ofs, vwv, sizeof(uint16_t) * wct);
- ofs += sizeof(uint16_t) * wct;
-
- /*
- * bcc (byte count)
- */
-
- SSVAL(outbuf, ofs, num_bytes + bytes_padding);
- ofs += sizeof(uint16_t);
-
- /*
- * padding
- */
-
- if (bytes_padding != 0) {
- memset(outbuf + ofs, 0, bytes_padding);
- ofs += bytes_padding;
- }
-
- /*
- * The bytes field
- */
-
- memcpy(outbuf + ofs, bytes, num_bytes);
-
- return true;
-}
-
-/**
* Figure out if there is an andx command behind the current one
* @param[in] buf The smb buffer to look at
* @param[in] ofs The offset to the wct field that is followed by the cmd
@@ -556,6 +382,7 @@ struct tevent_req *cli_smb_req_create(TALLOC_CTX *mem_ctx,
{
struct tevent_req *result;
struct cli_smb_state *state;
+ struct timeval endtime;
if (iov_count > MAX_SMB_IOV) {
/*
@@ -596,6 +423,10 @@ struct tevent_req *cli_smb_req_create(TALLOC_CTX *mem_ctx,
}
state->iov_count = iov_count + 3;
+ endtime = timeval_current_ofs(0, cli->timeout * 1000);
+ if (!tevent_req_set_endtime(result, ev, endtime)) {
+ tevent_req_nomem(NULL, result);
+ }
return result;
}
@@ -679,12 +510,10 @@ static NTSTATUS cli_smb_req_iov_send(struct tevent_req *req,
}
iov[0].iov_base = (void *)buf;
iov[0].iov_len = talloc_get_size(buf);
- subreq = writev_send(state, state->ev, state->cli->outgoing,
- state->cli->fd, false, iov, 1);
- } else {
- subreq = writev_send(state, state->ev, state->cli->outgoing,
- state->cli->fd, false, iov, iov_count);
+ iov_count = 1;
}
+ subreq = writev_send(state, state->ev, state->cli->outgoing,
+ state->cli->fd, false, iov, iov_count);
if (subreq == NULL) {
return NT_STATUS_NO_MEMORY;
}
@@ -986,16 +815,30 @@ NTSTATUS cli_smb_recv(struct tevent_req *req, uint8_t min_wct,
status = cli_pull_error((char *)state->inbuf);
- if (!have_andx_command((char *)state->inbuf, wct_ofs)
- && NT_STATUS_IS_ERR(status)) {
- /*
- * The last command takes the error code. All further commands
- * down the requested chain will get a
- * NT_STATUS_REQUEST_ABORTED.
- */
- return status;
+ if (!have_andx_command((char *)state->inbuf, wct_ofs)) {
+
+ if ((cmd == SMBsesssetupX)
+ && NT_STATUS_EQUAL(
+ status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+ /*
+ * NT_STATUS_MORE_PROCESSING_REQUIRED is a
+ * valid return code for session setup
+ */
+ goto no_err;
+ }
+
+ if (NT_STATUS_IS_ERR(status)) {
+ /*
+ * The last command takes the error code. All
+ * further commands down the requested chain
+ * will get a NT_STATUS_REQUEST_ABORTED.
+ */
+ return status;
+ }
}
+no_err:
+
wct = CVAL(state->inbuf, wct_ofs);
bytes_offset = wct_ofs + 1 + wct * sizeof(uint16_t);
num_bytes = SVAL(state->inbuf, bytes_offset);
@@ -1027,7 +870,7 @@ NTSTATUS cli_smb_recv(struct tevent_req *req, uint8_t min_wct,
*pbytes = (uint8_t *)state->inbuf + bytes_offset + 2;
}
- return NT_STATUS_OK;
+ return status;
}
size_t cli_smb_wct_ofs(struct tevent_req **reqs, int num_reqs)
diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 112143ca96..31216b8240 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -3,17 +3,17 @@
client connect/disconnect routines
Copyright (C) Andrew Tridgell 1994-1998
Copyright (C) Andrew Bartlett 2001-2003
-
+
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/>.
*/
@@ -22,6 +22,7 @@
#include "../libcli/auth/libcli_auth.h"
#include "../libcli/auth/spnego.h"
#include "smb_krb5.h"
+#include "ntlmssp.h"
static const struct {
int prot;
@@ -104,7 +105,7 @@ static NTSTATUS cli_session_setup_lanman2(struct cli_state *cli,
cli_set_message(cli->outbuf,10, 0, True);
SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
cli_setup_packet(cli);
-
+
SCVAL(cli->outbuf,smb_vwv0,0xFF);
SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit);
SSVAL(cli->outbuf,smb_vwv3,2);
@@ -130,7 +131,7 @@ static NTSTATUS cli_session_setup_lanman2(struct cli_state *cli,
if (cli_is_error(cli)) {
return cli_nt_error(cli);
}
-
+
/* use the returned vuid from now on */
cli->vuid = SVAL(cli->inbuf,smb_uid);
status = cli_set_username(cli, user);
@@ -359,14 +360,14 @@ static NTSTATUS cli_session_setup_plaintext(struct cli_state *cli,
char *p;
NTSTATUS status;
fstring lanman;
-
+
fstr_sprintf( lanman, "Samba %s", samba_version_string());
memset(cli->outbuf, '\0', smb_size);
cli_set_message(cli->outbuf,13,0,True);
SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
cli_setup_packet(cli);
-
+
SCVAL(cli->outbuf,smb_vwv0,0xFF);
SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
SSVAL(cli->outbuf,smb_vwv3,2);
@@ -375,9 +376,9 @@ static NTSTATUS cli_session_setup_plaintext(struct cli_state *cli,
SSVAL(cli->outbuf,smb_vwv8,0);
SIVAL(cli->outbuf,smb_vwv11,capabilities);
p = smb_buf(cli->outbuf);
-
+
/* check wether to send the ASCII or UNICODE version of the password */
-
+
if ( (capabilities & CAP_UNICODE) == 0 ) {
p += clistr_push(cli, p, pass, -1, STR_TERMINATE); /* password */
SSVAL(cli->outbuf,smb_vwv7,PTR_DIFF(p, smb_buf(cli->outbuf)));
@@ -393,7 +394,7 @@ static NTSTATUS cli_session_setup_plaintext(struct cli_state *cli,
p += clistr_push(cli, p, pass, -1, STR_UNICODE|STR_TERMINATE); /* unicode password */
SSVAL(cli->outbuf,smb_vwv8,PTR_DIFF(p, smb_buf(cli->outbuf))-1);
}
-
+
p += clistr_push(cli, p, user, -1, STR_TERMINATE); /* username */
p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE); /* workgroup */
p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
@@ -403,9 +404,9 @@ static NTSTATUS cli_session_setup_plaintext(struct cli_state *cli,
if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
return cli_nt_error(cli);
}
-
+
show_msg(cli->inbuf);
-
+
if (cli_is_error(cli)) {
return cli_nt_error(cli);
}
@@ -524,7 +525,7 @@ static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user,
cli_set_message(cli->outbuf,13,0,True);
SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
cli_setup_packet(cli);
-
+
SCVAL(cli->outbuf,smb_vwv0,0xFF);
SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
SSVAL(cli->outbuf,smb_vwv3,2);
@@ -574,7 +575,7 @@ static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user,
/* use the returned vuid from now on */
cli->vuid = SVAL(cli->inbuf,smb_uid);
-
+
p = smb_buf(cli->inbuf);
p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
-1, STR_TERMINATE);
@@ -605,172 +606,212 @@ end:
return result;
}
-/****************************************************************************
- Send a extended security session setup blob
-****************************************************************************/
+/* The following is calculated from :
+ * (smb_size-4) = 35
+ * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
+ * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
+ * end of packet.
+ */
-static bool cli_session_setup_blob_send(struct cli_state *cli, DATA_BLOB blob)
-{
- uint32 capabilities = cli_session_setup_capabilities(cli);
- char *p;
+#define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
- capabilities |= CAP_EXTENDED_SECURITY;
+struct cli_sesssetup_blob_state {
+ struct tevent_context *ev;
+ struct cli_state *cli;
+ DATA_BLOB blob;
+ uint16_t max_blob_size;
+ uint16_t vwv[12];
+ uint8_t *buf;
- /* send a session setup command */
- memset(cli->outbuf,'\0',smb_size);
+ NTSTATUS status;
+ char *inbuf;
+ DATA_BLOB ret_blob;
+};
- cli_set_message(cli->outbuf,12,0,True);
- SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
+static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
+ struct tevent_req **psubreq);
+static void cli_sesssetup_blob_done(struct tevent_req *subreq);
- cli_setup_packet(cli);
+static struct tevent_req *cli_sesssetup_blob_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct cli_state *cli,
+ DATA_BLOB blob)
+{
+ struct tevent_req *req, *subreq;
+ struct cli_sesssetup_blob_state *state;
- SCVAL(cli->outbuf,smb_vwv0,0xFF);
- SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
- SSVAL(cli->outbuf,smb_vwv3,2);
- SSVAL(cli->outbuf,smb_vwv4,1);
- SIVAL(cli->outbuf,smb_vwv5,0);
- SSVAL(cli->outbuf,smb_vwv7,blob.length);
- SIVAL(cli->outbuf,smb_vwv10,capabilities);
- p = smb_buf(cli->outbuf);
- memcpy(p, blob.data, blob.length);
- p += blob.length;
- p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
- p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
- cli_setup_bcc(cli, p);
- return cli_send_smb(cli);
-}
+ req = tevent_req_create(mem_ctx, &state,
+ struct cli_sesssetup_blob_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ state->ev = ev;
+ state->blob = blob;
+ state->cli = cli;
-/****************************************************************************
- Send a extended security session setup blob, returning a reply blob.
-****************************************************************************/
+ if (cli->max_xmit < BASE_SESSSETUP_BLOB_PACKET_SIZE + 1) {
+ DEBUG(1, ("cli_session_setup_blob: cli->max_xmit too small "
+ "(was %u, need minimum %u)\n",
+ (unsigned int)cli->max_xmit,
+ BASE_SESSSETUP_BLOB_PACKET_SIZE));
+ tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ return tevent_req_post(req, ev);
+ }
+ state->max_blob_size =
+ MIN(cli->max_xmit - BASE_SESSSETUP_BLOB_PACKET_SIZE, 0xFFFF);
-static DATA_BLOB cli_session_setup_blob_receive(struct cli_state *cli)
+ if (!cli_sesssetup_blob_next(state, &subreq)) {
+ tevent_req_nomem(NULL, req);
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
+ return req;
+}
+
+static bool cli_sesssetup_blob_next(struct cli_sesssetup_blob_state *state,
+ struct tevent_req **psubreq)
{
- DATA_BLOB blob2 = data_blob_null;
- char *p;
- size_t len;
+ struct tevent_req *subreq;
+ uint16_t thistime;
+
+ SCVAL(state->vwv+0, 0, 0xFF);
+ SCVAL(state->vwv+0, 1, 0);
+ SSVAL(state->vwv+1, 0, 0);
+ SSVAL(state->vwv+2, 0, CLI_BUFFER_SIZE);
+ SSVAL(state->vwv+3, 0, 2);
+ SSVAL(state->vwv+4, 0, 1);
+ SIVAL(state->vwv+5, 0, 0);
+
+ thistime = MIN(state->blob.length, state->max_blob_size);
+ SSVAL(state->vwv+7, 0, thistime);
+
+ SSVAL(state->vwv+8, 0, 0);
+ SSVAL(state->vwv+9, 0, 0);
+ SIVAL(state->vwv+10, 0,
+ cli_session_setup_capabilities(state->cli)
+ | CAP_EXTENDED_SECURITY);
+
+ state->buf = (uint8_t *)talloc_memdup(state, state->blob.data,
+ thistime);
+ if (state->buf == NULL) {
+ return false;
+ }
+ state->blob.data += thistime;
+ state->blob.length -= thistime;
- if (!cli_receive_smb(cli))
- return blob2;
+ state->buf = smb_bytes_push_str(state->buf, cli_ucs2(state->cli),
+ "Unix", 5, NULL);
+ state->buf = smb_bytes_push_str(state->buf, cli_ucs2(state->cli),
+ "Samba", 6, NULL);
+ if (state->buf == NULL) {
+ return false;
+ }
+ subreq = cli_smb_send(state, state->ev, state->cli, SMBsesssetupX, 0,
+ 12, state->vwv,
+ talloc_get_size(state->buf), state->buf);
+ if (subreq == NULL) {
+ return false;
+ }
+ *psubreq = subreq;
+ return true;
+}
- show_msg(cli->inbuf);
+static void cli_sesssetup_blob_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct cli_sesssetup_blob_state *state = tevent_req_data(
+ req, struct cli_sesssetup_blob_state);
+ struct cli_state *cli = state->cli;
+ uint8_t wct;
+ uint16_t *vwv;
+ uint32_t num_bytes;
+ uint8_t *bytes;
+ NTSTATUS status;
+ uint8_t *p;
+ uint16_t blob_length;
- if (cli_is_error(cli) && !NT_STATUS_EQUAL(cli_nt_error(cli),
- NT_STATUS_MORE_PROCESSING_REQUIRED)) {
- return blob2;
+ status = cli_smb_recv(subreq, 1, &wct, &vwv, &num_bytes, &bytes);
+ if (!NT_STATUS_IS_OK(status)
+ && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+ TALLOC_FREE(subreq);
+ tevent_req_nterror(req, status);
+ return;
}
- /* use the returned vuid from now on */
- cli->vuid = SVAL(cli->inbuf,smb_uid);
+ state->status = status;
+ TALLOC_FREE(state->buf);
- p = smb_buf(cli->inbuf);
+ state->inbuf = (char *)cli_smb_inbuf(subreq);
+ cli->vuid = SVAL(state->inbuf, smb_uid);
+
+ blob_length = SVAL(vwv+3, 0);
+ if (blob_length > num_bytes) {
+ TALLOC_FREE(subreq);
+ tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
+ return;
+ }
+ state->ret_blob = data_blob_const(bytes, blob_length);
- blob2 = data_blob(p, SVAL(cli->inbuf, smb_vwv3));
+ p = bytes + blob_length;
- p += blob2.length;
- p += clistr_pull(cli->inbuf, cli->server_os, p, sizeof(fstring),
- -1, STR_TERMINATE);
+ p += clistr_pull(state->inbuf, cli->server_os,
+ (char *)p, sizeof(fstring),
+ bytes+num_bytes-p, STR_TERMINATE);
+ p += clistr_pull(state->inbuf, cli->server_type,
+ (char *)p, sizeof(fstring),
+ bytes+num_bytes-p, STR_TERMINATE);
+ p += clistr_pull(state->inbuf, cli->server_domain,
+ (char *)p, sizeof(fstring),
+ bytes+num_bytes-p, STR_TERMINATE);
- /* w2k with kerberos doesn't properly null terminate this field */
- len = smb_bufrem(cli->inbuf, p);
- if (p + len < cli->inbuf + cli->bufsize+SAFETY_MARGIN - 2) {
- char *end_of_buf = p + len;
+ if (strstr(cli->server_type, "Samba")) {
+ cli->is_samba = True;
+ }
- SSVAL(p, len, 0);
- /* Now it's null terminated. */
- p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
- -1, STR_TERMINATE);
+ if (state->blob.length != 0) {
+ TALLOC_FREE(subreq);
/*
- * See if there's another string. If so it's the
- * server domain (part of the 'standard' Samba
- * server signature).
+ * More to send
*/
- if (p < end_of_buf) {
- p += clistr_pull(cli->inbuf, cli->server_domain, p, sizeof(fstring),
- -1, STR_TERMINATE);
+ if (!cli_sesssetup_blob_next(state, &subreq)) {
+ tevent_req_nomem(NULL, req);
+ return;
}
- } else {
- /*
- * No room to null terminate so we can't see if there
- * is another string (server_domain) afterwards.
- */
- p += clistr_pull(cli->inbuf, cli->server_type, p, sizeof(fstring),
- len, 0);
+ tevent_req_set_callback(subreq, cli_sesssetup_blob_done, req);
+ return;
}
- return blob2;
+ tevent_req_done(req);
}
-#ifdef HAVE_KRB5
-/****************************************************************************
- Send a extended security session setup blob, returning a reply blob.
-****************************************************************************/
-
-/* The following is calculated from :
- * (smb_size-4) = 35
- * (smb_wcnt * 2) = 24 (smb_wcnt == 12 in cli_session_setup_blob_send() )
- * (strlen("Unix") + 1 + strlen("Samba") + 1) * 2 = 22 (unicode strings at
- * end of packet.
- */
-
-#define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
-
-static bool cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob)
+static NTSTATUS cli_sesssetup_blob_recv(struct tevent_req *req,
+ TALLOC_CTX *mem_ctx,
+ DATA_BLOB *pblob,
+ char **pinbuf)
{
- int32 remaining = blob.length;
- int32 cur = 0;
- DATA_BLOB send_blob = data_blob_null;
- int32 max_blob_size = 0;
- DATA_BLOB receive_blob = data_blob_null;
+ struct cli_sesssetup_blob_state *state = tevent_req_data(
+ req, struct cli_sesssetup_blob_state);
+ NTSTATUS status;
+ char *inbuf;
- if (cli->max_xmit < BASE_SESSSETUP_BLOB_PACKET_SIZE + 1) {
- DEBUG(0,("cli_session_setup_blob: cli->max_xmit too small "
- "(was %u, need minimum %u)\n",
- (unsigned int)cli->max_xmit,
- BASE_SESSSETUP_BLOB_PACKET_SIZE));
- cli_set_nt_error(cli, NT_STATUS_INVALID_PARAMETER);
- return False;
+ if (tevent_req_is_nterror(req, &status)) {
+ state->cli->vuid = 0;
+ return status;
}
- max_blob_size = cli->max_xmit - BASE_SESSSETUP_BLOB_PACKET_SIZE;
-
- while ( remaining > 0) {
- if (remaining >= max_blob_size) {
- send_blob.length = max_blob_size;
- remaining -= max_blob_size;
- } else {
- send_blob.length = remaining;
- remaining = 0;
- }
-
- send_blob.data = &blob.data[cur];
- cur += send_blob.length;
-
- DEBUG(10, ("cli_session_setup_blob: Remaining (%u) sending (%u) current (%u)\n",
- (unsigned int)remaining,
- (unsigned int)send_blob.length,
- (unsigned int)cur ));
-
- if (!cli_session_setup_blob_send(cli, send_blob)) {
- DEBUG(0, ("cli_session_setup_blob: send failed\n"));
- return False;
- }
-
- receive_blob = cli_session_setup_blob_receive(cli);
- data_blob_free(&receive_blob);
-
- if (cli_is_error(cli) &&
- !NT_STATUS_EQUAL( cli_get_nt_error(cli),
- NT_STATUS_MORE_PROCESSING_REQUIRED)) {
- DEBUG(0, ("cli_session_setup_blob: receive failed "
- "(%s)\n", nt_errstr(cli_get_nt_error(cli))));
- cli->vuid = 0;
- return False;
- }
+ inbuf = talloc_move(mem_ctx, &state->inbuf);
+ if (pblob != NULL) {
+ *pblob = state->ret_blob;
}
-
- return True;
+ if (pinbuf != NULL) {
+ *pinbuf = inbuf;
+ }
+ /* could be NT_STATUS_MORE_PROCESSING_REQUIRED */
+ return state->status;
}
+#ifdef HAVE_KRB5
+
/****************************************************************************
Use in-memory credentials cache
****************************************************************************/
@@ -783,187 +824,358 @@ static void use_in_memory_ccache(void) {
Do a spnego/kerberos encrypted session setup.
****************************************************************************/
-static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli, const char *principal, const char *workgroup)
-{
+struct cli_session_setup_kerberos_state {
+ struct cli_state *cli;
DATA_BLOB negTokenTarg;
DATA_BLOB session_key_krb5;
- NTSTATUS nt_status;
- int rc;
+ ADS_STATUS ads_status;
+};
- cli_temp_set_signing(cli);
+static void cli_session_setup_kerberos_done(struct tevent_req *subreq);
+
+static struct tevent_req *cli_session_setup_kerberos_send(
+ TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
+ const char *principal, const char *workgroup)
+{
+ struct tevent_req *req, *subreq;
+ struct cli_session_setup_kerberos_state *state;
+ int rc;
DEBUG(2,("Doing kerberos session setup\n"));
- /* generate the encapsulated kerberos5 ticket */
- rc = spnego_gen_negTokenTarg(principal, 0, &negTokenTarg, &session_key_krb5, 0, NULL);
+ req = tevent_req_create(mem_ctx, &state,
+ struct cli_session_setup_kerberos_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ state->cli = cli;
+ state->ads_status = ADS_SUCCESS;
+
+ cli_temp_set_signing(cli);
+ /*
+ * Ok, this is cheated: spnego_gen_negTokenTarg can block if
+ * we have to acquire a ticket. To be fixed later :-)
+ */
+ rc = spnego_gen_negTokenTarg(principal, 0, &state->negTokenTarg,
+ &state->session_key_krb5, 0, NULL);
if (rc) {
- DEBUG(1, ("cli_session_setup_kerberos: spnego_gen_negTokenTarg failed: %s\n",
- error_message(rc)));
- return ADS_ERROR_KRB5(rc);
+ DEBUG(1, ("cli_session_setup_kerberos: "
+ "spnego_gen_negTokenTarg failed: %s\n",
+ error_message(rc)));
+ state->ads_status = ADS_ERROR_KRB5(rc);
+ tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
+ return tevent_req_post(req, ev);
}
#if 0
- file_save("negTokenTarg.dat", negTokenTarg.data, negTokenTarg.length);
+ file_save("negTokenTarg.dat", state->negTokenTarg.data,
+ state->negTokenTarg.length);
#endif
- if (!cli_session_setup_blob(cli, negTokenTarg)) {
- nt_status = cli_nt_error(cli);
- goto nt_error;
+ subreq = cli_sesssetup_blob_send(state, ev, cli, state->negTokenTarg);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
}
+ tevent_req_set_callback(subreq, cli_session_setup_kerberos_done, req);
+ return req;
+}
- if (cli_is_error(cli)) {
- nt_status = cli_nt_error(cli);
- if (NT_STATUS_IS_OK(nt_status)) {
- nt_status = NT_STATUS_UNSUCCESSFUL;
- }
- goto nt_error;
- }
+static void cli_session_setup_kerberos_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct cli_session_setup_kerberos_state *state = tevent_req_data(
+ req, struct cli_session_setup_kerberos_state);
+ char *inbuf = NULL;
+ NTSTATUS status;
- cli_set_session_key(cli, session_key_krb5);
+ status = cli_sesssetup_blob_recv(subreq, talloc_tos(), NULL, &inbuf);
+ if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(subreq);
+ tevent_req_nterror(req, status);
+ return;
+ }
- if (cli_simple_set_signing(
- cli, session_key_krb5, data_blob_null)) {
+ cli_set_session_key(state->cli, state->session_key_krb5);
- if (!cli_check_sign_mac(cli, cli->inbuf, 1)) {
- nt_status = NT_STATUS_ACCESS_DENIED;
- goto nt_error;
- }
+ if (cli_simple_set_signing(state->cli, state->session_key_krb5,
+ data_blob_null)
+ && !cli_check_sign_mac(state->cli, inbuf, 1)) {
+ TALLOC_FREE(subreq);
+ tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
+ return;
}
+ TALLOC_FREE(subreq);
+ tevent_req_done(req);
+}
+
+static ADS_STATUS cli_session_setup_kerberos_recv(struct tevent_req *req)
+{
+ struct cli_session_setup_kerberos_state *state = tevent_req_data(
+ req, struct cli_session_setup_kerberos_state);
+ NTSTATUS status;
- data_blob_free(&negTokenTarg);
- data_blob_free(&session_key_krb5);
+ if (tevent_req_is_nterror(req, &status)) {
+ return ADS_ERROR_NT(status);
+ }
+ return state->ads_status;
+}
- return ADS_ERROR_NT(NT_STATUS_OK);
+static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli,
+ const char *principal,
+ const char *workgroup)
+{
+ struct tevent_context *ev;
+ struct tevent_req *req;
+ ADS_STATUS status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
-nt_error:
- data_blob_free(&negTokenTarg);
- data_blob_free(&session_key_krb5);
- cli->vuid = 0;
- return ADS_ERROR_NT(nt_status);
+ if (cli_has_async_calls(cli)) {
+ return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+ }
+ ev = tevent_context_init(talloc_tos());
+ if (ev == NULL) {
+ goto fail;
+ }
+ req = cli_session_setup_kerberos_send(ev, ev, cli, principal,
+ workgroup);
+ if (req == NULL) {
+ goto fail;
+ }
+ if (!tevent_req_poll(req, ev)) {
+ status = ADS_ERROR_SYSTEM(errno);
+ goto fail;
+ }
+ status = cli_session_setup_kerberos_recv(req);
+fail:
+ TALLOC_FREE(ev);
+ return status;
}
#endif /* HAVE_KRB5 */
-
/****************************************************************************
Do a spnego/NTLMSSP encrypted session setup.
****************************************************************************/
-static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *user,
- const char *pass, const char *domain)
-{
+struct cli_session_setup_ntlmssp_state {
+ struct tevent_context *ev;
+ struct cli_state *cli;
struct ntlmssp_state *ntlmssp_state;
- NTSTATUS nt_status;
- int turn = 1;
- DATA_BLOB msg1;
- DATA_BLOB blob = data_blob_null;
- DATA_BLOB blob_in = data_blob_null;
- DATA_BLOB blob_out = data_blob_null;
+ int turn;
+ DATA_BLOB blob_out;
+};
- cli_temp_set_signing(cli);
+static int cli_session_setup_ntlmssp_state_destructor(
+ struct cli_session_setup_ntlmssp_state *state)
+{
+ if (state->ntlmssp_state != NULL) {
+ ntlmssp_end(&state->ntlmssp_state);
+ }
+ return 0;
+}
- if (!NT_STATUS_IS_OK(nt_status = ntlmssp_client_start(&ntlmssp_state))) {
- return nt_status;
+static void cli_session_setup_ntlmssp_done(struct tevent_req *req);
+
+static struct tevent_req *cli_session_setup_ntlmssp_send(
+ TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
+ const char *user, const char *pass, const char *domain)
+{
+ struct tevent_req *req, *subreq;
+ struct cli_session_setup_ntlmssp_state *state;
+ NTSTATUS status;
+ DATA_BLOB blob_out;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct cli_session_setup_ntlmssp_state);
+ if (req == NULL) {
+ return NULL;
}
- ntlmssp_want_feature(ntlmssp_state, NTLMSSP_FEATURE_SESSION_KEY);
+ state->ev = ev;
+ state->cli = cli;
+ state->turn = 1;
- if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, user))) {
- return nt_status;
+ state->ntlmssp_state = NULL;
+ talloc_set_destructor(
+ state, cli_session_setup_ntlmssp_state_destructor);
+
+ cli_temp_set_signing(cli);
+
+ status = ntlmssp_client_start(&state->ntlmssp_state);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto fail;
}
- if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, domain))) {
- return nt_status;
+ ntlmssp_want_feature(state->ntlmssp_state,
+ NTLMSSP_FEATURE_SESSION_KEY);
+ status = ntlmssp_set_username(state->ntlmssp_state, user);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto fail;
}
- if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_password(ntlmssp_state, pass))) {
- return nt_status;
+ status = ntlmssp_set_domain(state->ntlmssp_state, domain);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto fail;
+ }
+ status = ntlmssp_set_password(state->ntlmssp_state, pass);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto fail;
+ }
+ status = ntlmssp_update(state->ntlmssp_state, data_blob_null,
+ &blob_out);
+ if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+ goto fail;
}
- do {
- nt_status = ntlmssp_update(ntlmssp_state,
- blob_in, &blob_out);
- data_blob_free(&blob_in);
- if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED) || NT_STATUS_IS_OK(nt_status)) {
- if (turn == 1) {
- /* and wrap it in a SPNEGO wrapper */
- msg1 = gen_negTokenInit(OID_NTLMSSP, blob_out);
- } else {
- /* wrap it in SPNEGO */
- msg1 = spnego_gen_auth(blob_out);
- }
-
- /* now send that blob on its way */
- if (!cli_session_setup_blob_send(cli, msg1)) {
- DEBUG(3, ("Failed to send NTLMSSP/SPNEGO blob to server!\n"));
- nt_status = NT_STATUS_UNSUCCESSFUL;
- } else {
- blob = cli_session_setup_blob_receive(cli);
-
- nt_status = cli_nt_error(cli);
- if (cli_is_error(cli) && NT_STATUS_IS_OK(nt_status)) {
- if (cli->smb_rw_error == SMB_READ_BAD_SIG) {
- nt_status = NT_STATUS_ACCESS_DENIED;
- } else {
- nt_status = NT_STATUS_UNSUCCESSFUL;
- }
- }
- }
- data_blob_free(&msg1);
- }
+ state->blob_out = gen_negTokenInit(OID_NTLMSSP, blob_out);
+ data_blob_free(&blob_out);
- if (!blob.length) {
- if (NT_STATUS_IS_OK(nt_status)) {
- nt_status = NT_STATUS_UNSUCCESSFUL;
- }
- } else if ((turn == 1) &&
- NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
- DATA_BLOB tmp_blob = data_blob_null;
- /* the server might give us back two challenges */
- if (!spnego_parse_challenge(blob, &blob_in,
- &tmp_blob)) {
- DEBUG(3,("Failed to parse challenges\n"));
- nt_status = NT_STATUS_INVALID_PARAMETER;
- }
- data_blob_free(&tmp_blob);
- } else {
- if (!spnego_parse_auth_response(blob, nt_status, OID_NTLMSSP,
- &blob_in)) {
- DEBUG(3,("Failed to parse auth response\n"));
- if (NT_STATUS_IS_OK(nt_status)
- || NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED))
- nt_status = NT_STATUS_INVALID_PARAMETER;
- }
- }
- data_blob_free(&blob);
- data_blob_free(&blob_out);
- turn++;
- } while (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED));
+ subreq = cli_sesssetup_blob_send(state, ev, cli, state->blob_out);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
+ return req;
+fail:
+ tevent_req_nterror(req, status);
+ return tevent_req_post(req, ev);
+}
- data_blob_free(&blob_in);
+static void cli_session_setup_ntlmssp_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
+ req, struct cli_session_setup_ntlmssp_state);
+ DATA_BLOB blob_in, msg_in, blob_out;
+ char *inbuf = NULL;
+ bool parse_ret;
+ NTSTATUS status;
- if (NT_STATUS_IS_OK(nt_status)) {
+ status = cli_sesssetup_blob_recv(subreq, talloc_tos(), &blob_in,
+ &inbuf);
+ TALLOC_FREE(subreq);
+ data_blob_free(&state->blob_out);
- if (cli->server_domain[0] == '\0') {
- fstrcpy(cli->server_domain, ntlmssp_state->server_domain);
+ if (NT_STATUS_IS_OK(status)) {
+ if (state->cli->server_domain[0] == '\0') {
+ fstrcpy(state->cli->server_domain,
+ state->ntlmssp_state->server_domain);
}
- cli_set_session_key(cli, ntlmssp_state->session_key);
+ cli_set_session_key(
+ state->cli, state->ntlmssp_state->session_key);
if (cli_simple_set_signing(
- cli, ntlmssp_state->session_key, data_blob_null)) {
+ state->cli, state->ntlmssp_state->session_key,
+ data_blob_null)
+ && !cli_check_sign_mac(state->cli, inbuf, 1)) {
+ TALLOC_FREE(subreq);
+ tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
+ return;
+ }
+ TALLOC_FREE(subreq);
+ ntlmssp_end(&state->ntlmssp_state);
+ tevent_req_done(req);
+ return;
+ }
+ if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+ tevent_req_nterror(req, status);
+ return;
+ }
- if (!cli_check_sign_mac(cli, cli->inbuf, 1)) {
- nt_status = NT_STATUS_ACCESS_DENIED;
- }
+ if (blob_in.length == 0) {
+ tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
+ return;
+ }
+
+ if ((state->turn == 1)
+ && NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+ DATA_BLOB tmp_blob = data_blob_null;
+ /* the server might give us back two challenges */
+ parse_ret = spnego_parse_challenge(blob_in, &msg_in,
+ &tmp_blob);
+ data_blob_free(&tmp_blob);
+ } else {
+ parse_ret = spnego_parse_auth_response(blob_in, status,
+ OID_NTLMSSP, &msg_in);
+ }
+ state->turn += 1;
+
+ if (!parse_ret) {
+ DEBUG(3,("Failed to parse auth response\n"));
+ if (NT_STATUS_IS_OK(status)
+ || NT_STATUS_EQUAL(status,
+ NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+ tevent_req_nterror(
+ req, NT_STATUS_INVALID_NETWORK_RESPONSE);
+ return;
}
}
- /* we have a reference conter on ntlmssp_state, if we are signing
- then the state will be kept by the signing engine */
+ status = ntlmssp_update(state->ntlmssp_state, msg_in, &blob_out);
- ntlmssp_end(&ntlmssp_state);
+ if (!NT_STATUS_IS_OK(status)
+ && !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+ TALLOC_FREE(subreq);
+ ntlmssp_end(&state->ntlmssp_state);
+ tevent_req_nterror(req, status);
+ return;
+ }
- if (!NT_STATUS_IS_OK(nt_status)) {
- cli->vuid = 0;
+ state->blob_out = spnego_gen_auth(blob_out);
+ TALLOC_FREE(subreq);
+ if (tevent_req_nomem(state->blob_out.data, req)) {
+ return;
+ }
+
+ subreq = cli_sesssetup_blob_send(state, state->ev, state->cli,
+ state->blob_out);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, cli_session_setup_ntlmssp_done, req);
+}
+
+static NTSTATUS cli_session_setup_ntlmssp_recv(struct tevent_req *req)
+{
+ struct cli_session_setup_ntlmssp_state *state = tevent_req_data(
+ req, struct cli_session_setup_ntlmssp_state);
+ NTSTATUS status;
+
+ if (tevent_req_is_nterror(req, &status)) {
+ state->cli->vuid = 0;
+ return status;
+ }
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli,
+ const char *user,
+ const char *pass,
+ const char *domain)
+{
+ struct tevent_context *ev;
+ struct tevent_req *req;
+ NTSTATUS status = NT_STATUS_NO_MEMORY;
+
+ if (cli_has_async_calls(cli)) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ ev = tevent_context_init(talloc_tos());
+ if (ev == NULL) {
+ goto fail;
+ }
+ req = cli_session_setup_ntlmssp_send(ev, ev, cli, user, pass, domain);
+ if (req == NULL) {
+ goto fail;
}
- return nt_status;
+ if (!tevent_req_poll_ntstatus(req, ev, &status)) {
+ goto fail;
+ }
+ status = cli_session_setup_ntlmssp_recv(req);
+fail:
+ TALLOC_FREE(ev);
+ if (!NT_STATUS_IS_OK(status)) {
+ cli_set_error(cli, status);
+ }
+ return status;
}
/****************************************************************************
@@ -1251,25 +1463,88 @@ NTSTATUS cli_session_setup(struct cli_state *cli,
Send a uloggoff.
*****************************************************************************/
-bool cli_ulogoff(struct cli_state *cli)
+struct cli_ulogoff_state {
+ struct cli_state *cli;
+ uint16_t vwv[2];
+};
+
+static void cli_ulogoff_done(struct tevent_req *subreq);
+
+struct tevent_req *cli_ulogoff_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct cli_state *cli)
{
- memset(cli->outbuf,'\0',smb_size);
- cli_set_message(cli->outbuf,2,0,True);
- SCVAL(cli->outbuf,smb_com,SMBulogoffX);
- cli_setup_packet(cli);
- SSVAL(cli->outbuf,smb_vwv0,0xFF);
- SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
+ struct tevent_req *req, *subreq;
+ struct cli_ulogoff_state *state;
- cli_send_smb(cli);
- if (!cli_receive_smb(cli))
- return False;
+ req = tevent_req_create(mem_ctx, &state, struct cli_ulogoff_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ state->cli = cli;
- if (cli_is_error(cli)) {
- return False;
+ SCVAL(state->vwv+0, 0, 0xFF);
+ SCVAL(state->vwv+1, 0, 0);
+ SSVAL(state->vwv+2, 0, 0);
+
+ subreq = cli_smb_send(state, ev, cli, SMBulogoffX, 0, 2, state->vwv,
+ 0, NULL);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, cli_ulogoff_done, req);
+ return req;
+}
+
+static void cli_ulogoff_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct cli_ulogoff_state *state = tevent_req_data(
+ req, struct cli_ulogoff_state);
+ NTSTATUS status;
+
+ status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return;
}
+ state->cli->vuid = -1;
+ tevent_req_done(req);
+}
+
+NTSTATUS cli_ulogoff_recv(struct tevent_req *req)
+{
+ return tevent_req_simple_recv_ntstatus(req);
+}
+
+NTSTATUS cli_ulogoff(struct cli_state *cli)
+{
+ struct tevent_context *ev;
+ struct tevent_req *req;
+ NTSTATUS status = NT_STATUS_NO_MEMORY;
- cli->vuid = -1;
- return True;
+ if (cli_has_async_calls(cli)) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ ev = tevent_context_init(talloc_tos());
+ if (ev == NULL) {
+ goto fail;
+ }
+ req = cli_ulogoff_send(ev, ev, cli);
+ if (req == NULL) {
+ goto fail;
+ }
+ if (!tevent_req_poll_ntstatus(req, ev, &status)) {
+ goto fail;
+ }
+ status = cli_ulogoff_recv(req);
+fail:
+ TALLOC_FREE(ev);
+ if (!NT_STATUS_IS_OK(status)) {
+ cli_set_error(cli, status);
+ }
+ return status;
}
/****************************************************************************
@@ -1536,24 +1811,83 @@ NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share,
Send a tree disconnect.
****************************************************************************/
-bool cli_tdis(struct cli_state *cli)
+struct cli_tdis_state {
+ struct cli_state *cli;
+};
+
+static void cli_tdis_done(struct tevent_req *subreq);
+
+struct tevent_req *cli_tdis_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct cli_state *cli)
{
- memset(cli->outbuf,'\0',smb_size);
- cli_set_message(cli->outbuf,0,0,True);
- SCVAL(cli->outbuf,smb_com,SMBtdis);
- SSVAL(cli->outbuf,smb_tid,cli->cnum);
- cli_setup_packet(cli);
+ struct tevent_req *req, *subreq;
+ struct cli_tdis_state *state;
- cli_send_smb(cli);
- if (!cli_receive_smb(cli))
- return False;
+ req = tevent_req_create(mem_ctx, &state, struct cli_tdis_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ state->cli = cli;
- if (cli_is_error(cli)) {
- return False;
+ subreq = cli_smb_send(state, ev, cli, SMBtdis, 0, 0, NULL, 0, NULL);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
}
+ tevent_req_set_callback(subreq, cli_tdis_done, req);
+ return req;
+}
- cli->cnum = -1;
- return True;
+static void cli_tdis_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct cli_tdis_state *state = tevent_req_data(
+ req, struct cli_tdis_state);
+ NTSTATUS status;
+
+ status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return;
+ }
+ state->cli->cnum = -1;
+ tevent_req_done(req);
+}
+
+NTSTATUS cli_tdis_recv(struct tevent_req *req)
+{
+ return tevent_req_simple_recv_ntstatus(req);
+}
+
+NTSTATUS cli_tdis(struct cli_state *cli)
+{
+ struct tevent_context *ev;
+ struct tevent_req *req;
+ NTSTATUS status = NT_STATUS_NO_MEMORY;
+
+ if (cli_has_async_calls(cli)) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ ev = tevent_context_init(talloc_tos());
+ if (ev == NULL) {
+ goto fail;
+ }
+ req = cli_tdis_send(ev, ev, cli);
+ if (req == NULL) {
+ goto fail;
+ }
+ if (!tevent_req_poll_ntstatus(req, ev, &status)) {
+ goto fail;
+ }
+ status = cli_tdis_recv(req);
+fail:
+ TALLOC_FREE(ev);
+ if (!NT_STATUS_IS_OK(status)) {
+ cli_set_error(cli, status);
+ }
+ return status;
}
/****************************************************************************
@@ -1671,6 +2005,7 @@ static void cli_negprot_done(struct tevent_req *subreq)
status = cli_smb_recv(subreq, 1, &wct, &vwv, &num_bytes, &bytes);
if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(subreq);
+ tevent_req_nterror(req, status);
return;
}
diff --git a/source3/libsmb/clidfs.c b/source3/libsmb/clidfs.c
index afae4ff2ab..99f52f4ca7 100644
--- a/source3/libsmb/clidfs.c
+++ b/source3/libsmb/clidfs.c
@@ -993,6 +993,7 @@ bool cli_check_msdfs_proxy(TALLOC_CTX *ctx,
bool res;
uint16 cnum;
char *newextrapath = NULL;
+ NTSTATUS status;
if (!cli || !sharename) {
return false;
@@ -1020,7 +1021,7 @@ bool cli_check_msdfs_proxy(TALLOC_CTX *ctx,
}
if (force_encrypt) {
- NTSTATUS status = cli_cm_force_encryption(cli,
+ status = cli_cm_force_encryption(cli,
username,
password,
lp_workgroup(),
@@ -1032,7 +1033,8 @@ bool cli_check_msdfs_proxy(TALLOC_CTX *ctx,
res = cli_dfs_get_referral(ctx, cli, fullpath, &refs, &num_refs, &consumed);
- if (!cli_tdis(cli)) {
+ status = cli_tdis(cli);
+ if (!NT_STATUS_IS_OK(status)) {
return false;
}
diff --git a/source3/libsmb/clifsinfo.c b/source3/libsmb/clifsinfo.c
index ec690b4d82..38382e4af7 100644
--- a/source3/libsmb/clifsinfo.c
+++ b/source3/libsmb/clifsinfo.c
@@ -20,6 +20,7 @@
#include "includes.h"
#include "../libcli/auth/spnego.h"
+#include "ntlmssp.h"
/****************************************************************************
Get UNIX extensions version info.
diff --git a/source3/libsmb/conncache.c b/source3/libsmb/conncache.c
index b440d61048..85a09cc9ce 100644
--- a/source3/libsmb/conncache.c
+++ b/source3/libsmb/conncache.c
@@ -7,17 +7,18 @@
Copyright (C) Andrew Bartlett 2002
Copyright (C) Gerald (Jerry) Carter 2003
Copyright (C) Marc VanHeyningen 2008
-
+ Copyright (C) Volker Lendecke 2009
+
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/>.
*/
@@ -37,11 +38,6 @@
/**
- * prefix used for all entries put into the general cache
- */
-static const char NEGATIVE_CONN_CACHE_PREFIX[] = "NEG_CONN_CACHE";
-
-/**
* Marshalls the domain and server name into the key for the gencache
* record
*
@@ -53,15 +49,16 @@ static const char NEGATIVE_CONN_CACHE_PREFIX[] = "NEG_CONN_CACHE";
*/
static char *negative_conn_cache_keystr(const char *domain, const char *server)
{
- const char NEGATIVE_CONN_CACHE_KEY_FMT[] = "%s/%s,%s";
char *keystr = NULL;
- SMB_ASSERT(domain != NULL);
+ if (domain == NULL) {
+ return NULL;
+ }
if (server == NULL)
server = "";
- keystr = talloc_asprintf(talloc_tos(),NEGATIVE_CONN_CACHE_KEY_FMT,
- NEGATIVE_CONN_CACHE_PREFIX, domain, server);
+ keystr = talloc_asprintf(talloc_tos(), "NEG_CONN_CACHE/%s,%s",
+ domain, server);
if (keystr == NULL) {
DEBUG(0, ("negative_conn_cache_keystr: malloc error\n"));
}
@@ -100,13 +97,16 @@ static char *negative_conn_cache_valuestr(NTSTATUS status)
*/
static NTSTATUS negative_conn_cache_valuedecode(const char *value)
{
- NTSTATUS result = NT_STATUS_OK;
+ unsigned int v = NT_STATUS_V(NT_STATUS_INTERNAL_ERROR);;
- SMB_ASSERT(value != NULL);
- if (sscanf(value, "%x", &(NT_STATUS_V(result))) != 1)
- DEBUG(0, ("negative_conn_cache_valuestr: unable to parse "
+ if (value != NULL) {
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+ if (sscanf(value, "%x", &v) != 1) {
+ DEBUG(0, ("negative_conn_cache_valuedecode: unable to parse "
"value field '%s'\n", value));
- return result;
+ }
+ return NT_STATUS(v);
}
/**
@@ -143,7 +143,7 @@ NTSTATUS check_negative_conn_cache( const char *domain, const char *server)
if (key == NULL)
goto done;
- if (gencache_get(key, &value, (time_t *) NULL))
+ if (gencache_get(key, &value, NULL))
result = negative_conn_cache_valuedecode(value);
done:
DEBUG(9,("check_negative_conn_cache returning result %d for domain %s "
@@ -154,29 +154,6 @@ NTSTATUS check_negative_conn_cache( const char *domain, const char *server)
}
/**
- * Delete any negative cache entry for the given domain/server
- *
- * @param[in] domain
- * @param[in] server may be either a FQDN or an IP address
- */
-void delete_negative_conn_cache(const char *domain, const char *server)
-{
- char *key = NULL;
-
- key = negative_conn_cache_keystr(domain, server);
- if (key == NULL)
- goto done;
-
- gencache_del(key);
- DEBUG(9,("delete_negative_conn_cache removing domain %s server %s\n",
- domain, server));
- done:
- TALLOC_FREE(key);
- return;
-}
-
-
-/**
* Add an entry to the failed connection cache
*
* @param[in] domain
@@ -189,7 +166,10 @@ void add_failed_connection_entry(const char *domain, const char *server,
char *key = NULL;
char *value = NULL;
- SMB_ASSERT(!NT_STATUS_IS_OK(result));
+ if (NT_STATUS_IS_OK(result)) {
+ /* Nothing failed here */
+ return;
+ }
key = negative_conn_cache_keystr(domain, server);
if (key == NULL) {
@@ -204,15 +184,14 @@ void add_failed_connection_entry(const char *domain, const char *server,
}
if (gencache_set(key, value,
- time((time_t *) NULL)
- + FAILED_CONNECTION_CACHE_TIMEOUT))
+ time(NULL) + FAILED_CONNECTION_CACHE_TIMEOUT))
DEBUG(9,("add_failed_connection_entry: added domain %s (%s) "
"to failed conn cache\n", domain, server ));
else
DEBUG(1,("add_failed_connection_entry: failed to add "
"domain %s (%s) to failed conn cache\n",
domain, server));
-
+
done:
TALLOC_FREE(key);
TALLOC_FREE(value);
@@ -220,15 +199,6 @@ void add_failed_connection_entry(const char *domain, const char *server,
}
/**
- * Deletes all records from the negative connection cache in all domains
- */
-void flush_negative_conn_cache( void )
-{
- flush_negative_conn_cache_for_domain("*");
-}
-
-
-/**
* Deletes all records for a specified domain from the negative connection
* cache
*
@@ -246,10 +216,10 @@ void flush_negative_conn_cache_for_domain(const char *domain)
goto done;
}
- gencache_iterate(delete_matches, (void *) NULL, key_pattern);
+ gencache_iterate(delete_matches, NULL, key_pattern);
DEBUG(8, ("flush_negative_conn_cache_for_domain: flushed domain %s\n",
domain));
-
+
done:
TALLOC_FREE(key_pattern);
return;
diff --git a/source3/libsmb/errormap.c b/source3/libsmb/errormap.c
index 0285f22be4..48b3eb32d9 100644
--- a/source3/libsmb/errormap.c
+++ b/source3/libsmb/errormap.c
@@ -146,7 +146,7 @@ static const struct {
{ERRDOS, 87, NT_STATUS_BAD_WORKING_SET_LIMIT},
{ERRDOS, 87, NT_STATUS_INCOMPATIBLE_FILE_MAP},
{ERRDOS, 87, NT_STATUS_SECTION_PROTECTION},
- {ERRDOS, 282, NT_STATUS_EAS_NOT_SUPPORTED},
+ {ERRDOS, ERReasnotsupported, NT_STATUS_EAS_NOT_SUPPORTED},
{ERRDOS, 255, NT_STATUS_EA_TOO_LARGE},
{ERRHRD, ERRgeneral, NT_STATUS_NONEXISTENT_EA_ENTRY},
{ERRHRD, ERRgeneral, NT_STATUS_NO_EAS_ON_FILE},
@@ -708,7 +708,7 @@ static const struct {
{ERRDOS, 276, NT_STATUS_NONEXISTENT_EA_ENTRY},
{ERRDOS, 277, NT_STATUS_NONEXISTENT_EA_ENTRY},
{ERRDOS, 278, NT_STATUS_NONEXISTENT_EA_ENTRY},
- {ERRDOS, 282, NT_STATUS_EAS_NOT_SUPPORTED},
+ {ERRDOS, ERReasnotsupported, NT_STATUS_EAS_NOT_SUPPORTED},
{ERRDOS, 288, NT_STATUS_MUTANT_NOT_OWNED},
{ERRDOS, 298, NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED},
{ERRDOS, 299, NT_STATUS(0x8000000d)},
@@ -841,7 +841,7 @@ static const struct {
{ERRHRD, 276, NT_STATUS_NONEXISTENT_EA_ENTRY},
{ERRHRD, 277, NT_STATUS_NONEXISTENT_EA_ENTRY},
{ERRHRD, 278, NT_STATUS_NONEXISTENT_EA_ENTRY},
- {ERRHRD, 282, NT_STATUS_EAS_NOT_SUPPORTED},
+ {ERRHRD, ERReasnotsupported, NT_STATUS_EAS_NOT_SUPPORTED},
{ERRHRD, 288, NT_STATUS_MUTANT_NOT_OWNED},
{ERRHRD, 298, NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED},
{ERRHRD, 299, NT_STATUS(0x8000000d)},
diff --git a/source3/libsmb/libsmb_cache.c b/source3/libsmb/libsmb_cache.c
index 53cd3d5a77..f9770d363c 100644
--- a/source3/libsmb/libsmb_cache.c
+++ b/source3/libsmb/libsmb_cache.c
@@ -151,12 +151,14 @@ SMBC_get_cached_server(SMBCCTX * context,
* attribute server connection) is cool.
*/
if (smbc_getOptionOneSharePerServer(context)) {
+ NTSTATUS status;
/*
* The currently connected share name
* doesn't match the requested share, so
* disconnect from the current share.
*/
- if (! cli_tdis(srv->server->cli)) {
+ status = cli_tdis(srv->server->cli);
+ if (!NT_STATUS_IS_OK(status)) {
/* Sigh. Couldn't disconnect. */
cli_shutdown(srv->server->cli);
srv->server->cli = NULL;
diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c
index 60c1d49bb0..7fffe7cea3 100644
--- a/source3/libsmb/ntlmssp.c
+++ b/source3/libsmb/ntlmssp.c
@@ -22,9 +22,10 @@
*/
#include "includes.h"
+#include "ntlmssp.h"
#include "../libcli/auth/libcli_auth.h"
#include "../librpc/gen_ndr/ndr_ntlmssp.h"
-#include "libsmb/ntlmssp_ndr.h"
+#include "../libcli/auth/ntlmssp_ndr.h"
static NTSTATUS ntlmssp_client_initial(struct ntlmssp_state *ntlmssp_state,
DATA_BLOB reply, DATA_BLOB *next_request);
@@ -41,8 +42,8 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state,
*/
static const struct ntlmssp_callbacks {
- enum NTLMSSP_ROLE role;
- enum NTLM_MESSAGE_TYPE ntlmssp_command;
+ enum ntlmssp_role role;
+ enum ntlmssp_message_type ntlmssp_command;
NTSTATUS (*fn)(struct ntlmssp_state *ntlmssp_state,
DATA_BLOB in, DATA_BLOB *out);
} ntlmssp_callbacks[] = {
@@ -111,10 +112,11 @@ void debug_ntlmssp_flags(uint32 neg_flags)
*
*/
-static void get_challenge(const struct ntlmssp_state *ntlmssp_state,
- uint8_t chal[8])
+static NTSTATUS get_challenge(const struct ntlmssp_state *ntlmssp_state,
+ uint8_t chal[8])
{
generate_random_buffer(chal, 8);
+ return NT_STATUS_OK;
}
/**
@@ -145,7 +147,7 @@ static NTSTATUS set_challenge(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *ch
*
*/
-NTSTATUS ntlmssp_set_username(NTLMSSP_STATE *ntlmssp_state, const char *user)
+NTSTATUS ntlmssp_set_username(struct ntlmssp_state *ntlmssp_state, const char *user)
{
ntlmssp_state->user = talloc_strdup(ntlmssp_state, user ? user : "" );
if (!ntlmssp_state->user) {
@@ -158,7 +160,7 @@ NTSTATUS ntlmssp_set_username(NTLMSSP_STATE *ntlmssp_state, const char *user)
* Store NT and LM hashes on an NTLMSSP context - ensures they are talloc()ed
*
*/
-NTSTATUS ntlmssp_set_hashes(NTLMSSP_STATE *ntlmssp_state,
+NTSTATUS ntlmssp_set_hashes(struct ntlmssp_state *ntlmssp_state,
const unsigned char lm_hash[16],
const unsigned char nt_hash[16])
{
@@ -178,7 +180,7 @@ NTSTATUS ntlmssp_set_hashes(NTLMSSP_STATE *ntlmssp_state,
* Converts a password to the hashes on an NTLMSSP context.
*
*/
-NTSTATUS ntlmssp_set_password(NTLMSSP_STATE *ntlmssp_state, const char *password)
+NTSTATUS ntlmssp_set_password(struct ntlmssp_state *ntlmssp_state, const char *password)
{
if (!password) {
ntlmssp_state->lm_hash = NULL;
@@ -198,7 +200,7 @@ NTSTATUS ntlmssp_set_password(NTLMSSP_STATE *ntlmssp_state, const char *password
* Set a domain on an NTLMSSP context - ensures it is talloc()ed
*
*/
-NTSTATUS ntlmssp_set_domain(NTLMSSP_STATE *ntlmssp_state, const char *domain)
+NTSTATUS ntlmssp_set_domain(struct ntlmssp_state *ntlmssp_state, const char *domain)
{
ntlmssp_state->domain = talloc_strdup(ntlmssp_state,
domain ? domain : "" );
@@ -212,7 +214,7 @@ NTSTATUS ntlmssp_set_domain(NTLMSSP_STATE *ntlmssp_state, const char *domain)
* Set a workstation on an NTLMSSP context - ensures it is talloc()ed
*
*/
-NTSTATUS ntlmssp_set_workstation(NTLMSSP_STATE *ntlmssp_state, const char *workstation)
+NTSTATUS ntlmssp_set_workstation(struct ntlmssp_state *ntlmssp_state, const char *workstation)
{
ntlmssp_state->workstation = talloc_strdup(ntlmssp_state, workstation);
if (!ntlmssp_state->workstation) {
@@ -222,26 +224,12 @@ NTSTATUS ntlmssp_set_workstation(NTLMSSP_STATE *ntlmssp_state, const char *works
}
/**
- * Store a DATA_BLOB containing an NTLMSSP response, for use later.
- * This copies the data blob
- */
-
-NTSTATUS ntlmssp_store_response(NTLMSSP_STATE *ntlmssp_state,
- DATA_BLOB response)
-{
- ntlmssp_state->stored_response = data_blob_talloc(ntlmssp_state,
- response.data,
- response.length);
- return NT_STATUS_OK;
-}
-
-/**
* Request features for the NTLMSSP negotiation
*
* @param ntlmssp_state NTLMSSP state
* @param feature_list List of space seperated features requested from NTLMSSP.
*/
-void ntlmssp_want_feature_list(NTLMSSP_STATE *ntlmssp_state, char *feature_list)
+void ntlmssp_want_feature_list(struct ntlmssp_state *ntlmssp_state, char *feature_list)
{
/*
* We need to set this to allow a later SetPassword
@@ -265,7 +253,7 @@ void ntlmssp_want_feature_list(NTLMSSP_STATE *ntlmssp_state, char *feature_list)
* @param ntlmssp_state NTLMSSP state
* @param feature Bit flag specifying the requested feature
*/
-void ntlmssp_want_feature(NTLMSSP_STATE *ntlmssp_state, uint32 feature)
+void ntlmssp_want_feature(struct ntlmssp_state *ntlmssp_state, uint32 feature)
{
/* As per JRA's comment above */
if (feature & NTLMSSP_FEATURE_SESSION_KEY) {
@@ -288,10 +276,9 @@ void ntlmssp_want_feature(NTLMSSP_STATE *ntlmssp_state, uint32 feature)
* @return Errors, NT_STATUS_MORE_PROCESSING_REQUIRED or NT_STATUS_OK.
*/
-NTSTATUS ntlmssp_update(NTLMSSP_STATE *ntlmssp_state,
- const DATA_BLOB in, DATA_BLOB *out)
+NTSTATUS ntlmssp_update(struct ntlmssp_state *ntlmssp_state,
+ const DATA_BLOB input, DATA_BLOB *out)
{
- DATA_BLOB input;
uint32 ntlmssp_command;
int i;
@@ -303,15 +290,6 @@ NTSTATUS ntlmssp_update(NTLMSSP_STATE *ntlmssp_state,
*out = data_blob_null;
- if (!in.length && ntlmssp_state->stored_response.length) {
- input = ntlmssp_state->stored_response;
-
- /* we only want to read the stored response once - overwrite it */
- ntlmssp_state->stored_response = data_blob_null;
- } else {
- input = in;
- }
-
if (!input.length) {
switch (ntlmssp_state->role) {
case NTLMSSP_CLIENT:
@@ -356,16 +334,12 @@ NTSTATUS ntlmssp_update(NTLMSSP_STATE *ntlmssp_state,
* @param ntlmssp_state NTLMSSP State, free()ed by this function
*/
-void ntlmssp_end(NTLMSSP_STATE **ntlmssp_state)
+void ntlmssp_end(struct ntlmssp_state **ntlmssp_state)
{
- (*ntlmssp_state)->ref_count--;
-
- if ((*ntlmssp_state)->ref_count == 0) {
- data_blob_free(&(*ntlmssp_state)->chal);
- data_blob_free(&(*ntlmssp_state)->lm_resp);
- data_blob_free(&(*ntlmssp_state)->nt_resp);
- TALLOC_FREE(*ntlmssp_state);
- }
+ data_blob_free(&(*ntlmssp_state)->chal);
+ data_blob_free(&(*ntlmssp_state)->lm_resp);
+ data_blob_free(&(*ntlmssp_state)->nt_resp);
+ TALLOC_FREE(*ntlmssp_state);
*ntlmssp_state = NULL;
return;
@@ -466,7 +440,7 @@ static void ntlmssp_handle_neg_flags(struct ntlmssp_state *ntlmssp_state,
by the client lanman auth/lanman auth parameters, it isn't too bad.
*/
-DATA_BLOB ntlmssp_weaken_keys(NTLMSSP_STATE *ntlmssp_state, TALLOC_CTX *mem_ctx)
+DATA_BLOB ntlmssp_weaken_keys(struct ntlmssp_state *ntlmssp_state, TALLOC_CTX *mem_ctx)
{
DATA_BLOB weakened_key = data_blob_talloc(mem_ctx,
ntlmssp_state->session_key.data,
@@ -520,6 +494,7 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state,
const char *target_name;
struct NEGOTIATE_MESSAGE negotiate;
struct CHALLENGE_MESSAGE challenge;
+ NTSTATUS status;
/* parse the NTLMSSP packet */
#if 0
@@ -552,7 +527,10 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state,
ntlmssp_handle_neg_flags(ntlmssp_state, neg_flags, lp_lanman_auth());
/* Ask our caller what challenge they would like in the packet */
- ntlmssp_state->get_challenge(ntlmssp_state, cryptkey);
+ status = ntlmssp_state->get_challenge(ntlmssp_state, cryptkey);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
/* Check if we may set the challenge */
if (!ntlmssp_state->may_set_challenge(ntlmssp_state)) {
@@ -902,9 +880,9 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state,
* @param ntlmssp_state NTLMSSP State, allocated by this function
*/
-NTSTATUS ntlmssp_server_start(NTLMSSP_STATE **ntlmssp_state)
+NTSTATUS ntlmssp_server_start(struct ntlmssp_state **ntlmssp_state)
{
- *ntlmssp_state = TALLOC_ZERO_P(NULL, NTLMSSP_STATE);
+ *ntlmssp_state = TALLOC_ZERO_P(NULL, struct ntlmssp_state);
if (!*ntlmssp_state) {
DEBUG(0,("ntlmssp_server_start: talloc failed!\n"));
talloc_destroy(*ntlmssp_state);
@@ -923,8 +901,6 @@ NTSTATUS ntlmssp_server_start(NTLMSSP_STATE **ntlmssp_state)
(*ntlmssp_state)->expected_state = NTLMSSP_NEGOTIATE;
- (*ntlmssp_state)->ref_count = 1;
-
(*ntlmssp_state)->neg_flags =
NTLMSSP_NEGOTIATE_128 |
NTLMSSP_NEGOTIATE_56 |
@@ -1239,9 +1215,9 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state,
return nt_status;
}
-NTSTATUS ntlmssp_client_start(NTLMSSP_STATE **ntlmssp_state)
+NTSTATUS ntlmssp_client_start(struct ntlmssp_state **ntlmssp_state)
{
- *ntlmssp_state = TALLOC_ZERO_P(NULL, NTLMSSP_STATE);
+ *ntlmssp_state = TALLOC_ZERO_P(NULL, struct ntlmssp_state);
if (!*ntlmssp_state) {
DEBUG(0,("ntlmssp_client_start: talloc failed!\n"));
talloc_destroy(*ntlmssp_state);
@@ -1259,8 +1235,6 @@ NTSTATUS ntlmssp_client_start(NTLMSSP_STATE **ntlmssp_state)
(*ntlmssp_state)->expected_state = NTLMSSP_INITIAL;
- (*ntlmssp_state)->ref_count = 1;
-
(*ntlmssp_state)->neg_flags =
NTLMSSP_NEGOTIATE_128 |
NTLMSSP_NEGOTIATE_ALWAYS_SIGN |
diff --git a/source3/libsmb/ntlmssp_ndr.c b/source3/libsmb/ntlmssp_ndr.c
deleted file mode 100644
index 92cd677572..0000000000
--- a/source3/libsmb/ntlmssp_ndr.c
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- Unix SMB/Netbios implementation.
- NTLMSSP ndr functions
-
- Copyright (C) Guenther Deschner 2009
-
- 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"
-#include "../librpc/gen_ndr/ndr_ntlmssp.h"
-#include "libsmb/ntlmssp_ndr.h"
-
-#define NTLMSSP_PULL_MESSAGE(type, blob, mem_ctx, ic, r) \
-do { \
- enum ndr_err_code __ndr_err; \
- __ndr_err = ndr_pull_struct_blob(blob, mem_ctx, ic, r, \
- (ndr_pull_flags_fn_t)ndr_pull_ ##type); \
- if (!NDR_ERR_CODE_IS_SUCCESS(__ndr_err)) { \
- return ndr_map_error2ntstatus(__ndr_err); \
- } \
- if (memcmp(r->Signature, "NTLMSSP\0", 8)) {\
- return NT_STATUS_INVALID_PARAMETER; \
- } \
- return NT_STATUS_OK; \
-} while(0);
-
-#define NTLMSSP_PUSH_MESSAGE(type, blob, mem_ctx, ic, r) \
-do { \
- enum ndr_err_code __ndr_err; \
- __ndr_err = ndr_push_struct_blob(blob, mem_ctx, ic, r, \
- (ndr_push_flags_fn_t)ndr_push_ ##type); \
- if (!NDR_ERR_CODE_IS_SUCCESS(__ndr_err)) { \
- return ndr_map_error2ntstatus(__ndr_err); \
- } \
- return NT_STATUS_OK; \
-} while(0);
-
-
-/**
- * Pull NTLMSSP NEGOTIATE_MESSAGE struct from a blob
- * @param blob The plain packet blob
- * @param mem_ctx A talloc context
- * @param ic Iconv convenience structure
- * @param r Pointer to a NTLMSSP NEGOTIATE_MESSAGE structure
- */
-
-NTSTATUS ntlmssp_pull_NEGOTIATE_MESSAGE(const DATA_BLOB *blob,
- TALLOC_CTX *mem_ctx,
- struct smb_iconv_convenience *ic,
- struct NEGOTIATE_MESSAGE *r)
-{
- NTLMSSP_PULL_MESSAGE(NEGOTIATE_MESSAGE, blob, mem_ctx, ic, r);
-}
-
-/**
- * Pull NTLMSSP CHALLENGE_MESSAGE struct from a blob
- * @param blob The plain packet blob
- * @param mem_ctx A talloc context
- * @param ic Iconv convenience structure
- * @param r Pointer to a NTLMSSP CHALLENGE_MESSAGE structure
- */
-
-NTSTATUS ntlmssp_pull_CHALLENGE_MESSAGE(const DATA_BLOB *blob,
- TALLOC_CTX *mem_ctx,
- struct smb_iconv_convenience *ic,
- struct CHALLENGE_MESSAGE *r)
-{
- NTLMSSP_PULL_MESSAGE(CHALLENGE_MESSAGE, blob, mem_ctx, ic, r);
-}
-
-/**
- * Pull NTLMSSP AUTHENTICATE_MESSAGE struct from a blob
- * @param blob The plain packet blob
- * @param mem_ctx A talloc context
- * @param ic Iconv convenience structure
- * @param r Pointer to a NTLMSSP AUTHENTICATE_MESSAGE structure
- */
-
-NTSTATUS ntlmssp_pull_AUTHENTICATE_MESSAGE(const DATA_BLOB *blob,
- TALLOC_CTX *mem_ctx,
- struct smb_iconv_convenience *ic,
- struct AUTHENTICATE_MESSAGE *r)
-{
- NTLMSSP_PULL_MESSAGE(AUTHENTICATE_MESSAGE, blob, mem_ctx, ic, r);
-}
-
-/**
- * Push NTLMSSP NEGOTIATE_MESSAGE struct into a blob
- * @param blob The plain packet blob
- * @param mem_ctx A talloc context
- * @param ic Iconv convenience structure
- * @param r Pointer to a NTLMSSP NEGOTIATE_MESSAGE structure
- */
-
-NTSTATUS ntlmssp_push_NEGOTIATE_MESSAGE(DATA_BLOB *blob,
- TALLOC_CTX *mem_ctx,
- struct smb_iconv_convenience *ic,
- const struct NEGOTIATE_MESSAGE *r)
-{
- NTLMSSP_PUSH_MESSAGE(NEGOTIATE_MESSAGE, blob, mem_ctx, ic, r);
-}
-
-/**
- * Push NTLMSSP CHALLENGE_MESSAGE struct into a blob
- * @param blob The plain packet blob
- * @param mem_ctx A talloc context
- * @param ic Iconv convenience structure
- * @param r Pointer to a NTLMSSP CHALLENGE_MESSAGE structure
- */
-
-NTSTATUS ntlmssp_push_CHALLENGE_MESSAGE(DATA_BLOB *blob,
- TALLOC_CTX *mem_ctx,
- struct smb_iconv_convenience *ic,
- const struct CHALLENGE_MESSAGE *r)
-{
- NTLMSSP_PUSH_MESSAGE(CHALLENGE_MESSAGE, blob, mem_ctx, ic, r);
-}
-
-/**
- * Push NTLMSSP AUTHENTICATE_MESSAGE struct into a blob
- * @param blob The plain packet blob
- * @param mem_ctx A talloc context
- * @param ic Iconv convenience structure
- * @param r Pointer to a NTLMSSP AUTHENTICATE_MESSAGE structure
- */
-
-NTSTATUS ntlmssp_push_AUTHENTICATE_MESSAGE(DATA_BLOB *blob,
- TALLOC_CTX *mem_ctx,
- struct smb_iconv_convenience *ic,
- const struct AUTHENTICATE_MESSAGE *r)
-{
- NTLMSSP_PUSH_MESSAGE(AUTHENTICATE_MESSAGE, blob, mem_ctx, ic, r);
-}
diff --git a/source3/libsmb/ntlmssp_ndr.h b/source3/libsmb/ntlmssp_ndr.h
deleted file mode 100644
index 52990b2a56..0000000000
--- a/source3/libsmb/ntlmssp_ndr.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- Unix SMB/Netbios implementation.
- NTLMSSP ndr functions
-
- Copyright (C) Guenther Deschner 2009
-
- 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/>.
-*/
-
-NTSTATUS ntlmssp_pull_NEGOTIATE_MESSAGE(const DATA_BLOB *blob,
- TALLOC_CTX *mem_ctx,
- struct smb_iconv_convenience *ic,
- struct NEGOTIATE_MESSAGE *r);
-NTSTATUS ntlmssp_pull_CHALLENGE_MESSAGE(const DATA_BLOB *blob,
- TALLOC_CTX *mem_ctx,
- struct smb_iconv_convenience *ic,
- struct CHALLENGE_MESSAGE *r);
-NTSTATUS ntlmssp_pull_AUTHENTICATE_MESSAGE(const DATA_BLOB *blob,
- TALLOC_CTX *mem_ctx,
- struct smb_iconv_convenience *ic,
- struct AUTHENTICATE_MESSAGE *r);
-NTSTATUS ntlmssp_push_NEGOTIATE_MESSAGE(DATA_BLOB *blob,
- TALLOC_CTX *mem_ctx,
- struct smb_iconv_convenience *ic,
- const struct NEGOTIATE_MESSAGE *r);
-NTSTATUS ntlmssp_push_CHALLENGE_MESSAGE(DATA_BLOB *blob,
- TALLOC_CTX *mem_ctx,
- struct smb_iconv_convenience *ic,
- const struct CHALLENGE_MESSAGE *r);
-NTSTATUS ntlmssp_push_AUTHENTICATE_MESSAGE(DATA_BLOB *blob,
- TALLOC_CTX *mem_ctx,
- struct smb_iconv_convenience *ic,
- const struct AUTHENTICATE_MESSAGE *r);
diff --git a/source3/libsmb/ntlmssp_sign.c b/source3/libsmb/ntlmssp_sign.c
index 752749cdd8..3fd22ce73f 100644
--- a/source3/libsmb/ntlmssp_sign.c
+++ b/source3/libsmb/ntlmssp_sign.c
@@ -19,6 +19,7 @@
*/
#include "includes.h"
+#include "ntlmssp.h"
#include "../libcli/auth/libcli_auth.h"
#define CLI_SIGN "session key to client-to-server signing key magic constant"
@@ -58,7 +59,7 @@ enum ntlmssp_direction {
NTLMSSP_RECEIVE
};
-static NTSTATUS ntlmssp_make_packet_signature(NTLMSSP_STATE *ntlmssp_state,
+static NTSTATUS ntlmssp_make_packet_signature(struct ntlmssp_state *ntlmssp_state,
const uchar *data, size_t length,
const uchar *whole_pdu, size_t pdu_length,
enum ntlmssp_direction direction,
@@ -76,27 +77,27 @@ static NTSTATUS ntlmssp_make_packet_signature(NTLMSSP_STATE *ntlmssp_state,
}
switch (direction) {
- case NTLMSSP_SEND:
- DEBUG(100,("ntlmssp_make_packet_signature: SEND seq = %u, len = %u, pdu_len = %u\n",
- ntlmssp_state->ntlm2_send_seq_num,
- (unsigned int)length,
- (unsigned int)pdu_length));
-
- SIVAL(seq_num, 0, ntlmssp_state->ntlm2_send_seq_num);
- ntlmssp_state->ntlm2_send_seq_num++;
- hmac_md5_init_limK_to_64(ntlmssp_state->send_sign_key, 16, &ctx);
- break;
- case NTLMSSP_RECEIVE:
+ case NTLMSSP_SEND:
+ DEBUG(100,("ntlmssp_make_packet_signature: SEND seq = %u, len = %u, pdu_len = %u\n",
+ ntlmssp_state->ntlm2_send_seq_num,
+ (unsigned int)length,
+ (unsigned int)pdu_length));
+
+ SIVAL(seq_num, 0, ntlmssp_state->ntlm2_send_seq_num);
+ ntlmssp_state->ntlm2_send_seq_num++;
+ hmac_md5_init_limK_to_64(ntlmssp_state->send_sign_key, 16, &ctx);
+ break;
+ case NTLMSSP_RECEIVE:
- DEBUG(100,("ntlmssp_make_packet_signature: RECV seq = %u, len = %u, pdu_len = %u\n",
- ntlmssp_state->ntlm2_recv_seq_num,
- (unsigned int)length,
- (unsigned int)pdu_length));
+ DEBUG(100,("ntlmssp_make_packet_signature: RECV seq = %u, len = %u, pdu_len = %u\n",
+ ntlmssp_state->ntlm2_recv_seq_num,
+ (unsigned int)length,
+ (unsigned int)pdu_length));
- SIVAL(seq_num, 0, ntlmssp_state->ntlm2_recv_seq_num);
- ntlmssp_state->ntlm2_recv_seq_num++;
- hmac_md5_init_limK_to_64(ntlmssp_state->recv_sign_key, 16, &ctx);
- break;
+ SIVAL(seq_num, 0, ntlmssp_state->ntlm2_recv_seq_num);
+ ntlmssp_state->ntlm2_recv_seq_num++;
+ hmac_md5_init_limK_to_64(ntlmssp_state->recv_sign_key, 16, &ctx);
+ break;
}
dump_data_pw("pdu data ", whole_pdu, pdu_length);
@@ -137,7 +138,7 @@ static NTSTATUS ntlmssp_make_packet_signature(NTLMSSP_STATE *ntlmssp_state,
return NT_STATUS_OK;
}
-NTSTATUS ntlmssp_sign_packet(NTLMSSP_STATE *ntlmssp_state,
+NTSTATUS ntlmssp_sign_packet(struct ntlmssp_state *ntlmssp_state,
const uchar *data, size_t length,
const uchar *whole_pdu, size_t pdu_length,
DATA_BLOB *sig)
@@ -168,7 +169,7 @@ NTSTATUS ntlmssp_sign_packet(NTLMSSP_STATE *ntlmssp_state,
*
*/
-NTSTATUS ntlmssp_check_packet(NTLMSSP_STATE *ntlmssp_state,
+NTSTATUS ntlmssp_check_packet(struct ntlmssp_state *ntlmssp_state,
const uchar *data, size_t length,
const uchar *whole_pdu, size_t pdu_length,
const DATA_BLOB *sig)
@@ -236,7 +237,7 @@ NTSTATUS ntlmssp_check_packet(NTLMSSP_STATE *ntlmssp_state,
*
*/
-NTSTATUS ntlmssp_seal_packet(NTLMSSP_STATE *ntlmssp_state,
+NTSTATUS ntlmssp_seal_packet(struct ntlmssp_state *ntlmssp_state,
uchar *data, size_t length,
uchar *whole_pdu, size_t pdu_length,
DATA_BLOB *sig)
@@ -302,7 +303,7 @@ NTSTATUS ntlmssp_seal_packet(NTLMSSP_STATE *ntlmssp_state,
*
*/
-NTSTATUS ntlmssp_unseal_packet(NTLMSSP_STATE *ntlmssp_state,
+NTSTATUS ntlmssp_unseal_packet(struct ntlmssp_state *ntlmssp_state,
uchar *data, size_t length,
uchar *whole_pdu, size_t pdu_length,
DATA_BLOB *sig)
@@ -329,11 +330,9 @@ NTSTATUS ntlmssp_unseal_packet(NTLMSSP_STATE *ntlmssp_state,
/**
Initialise the state for NTLMSSP signing.
*/
-NTSTATUS ntlmssp_sign_init(NTLMSSP_STATE *ntlmssp_state)
+NTSTATUS ntlmssp_sign_init(struct ntlmssp_state *ntlmssp_state)
{
- unsigned char p24[24];
TALLOC_CTX *mem_ctx;
- ZERO_STRUCT(p24);
mem_ctx = talloc_init("weak_keys");
if (!mem_ctx) {
diff --git a/source3/libsmb/smb_seal.c b/source3/libsmb/smb_seal.c
index 2f7305c5b6..ec879db5b4 100644
--- a/source3/libsmb/smb_seal.c
+++ b/source3/libsmb/smb_seal.c
@@ -18,6 +18,7 @@
*/
#include "includes.h"
+#include "ntlmssp.h"
/******************************************************************************
Pull out the encryption context for this packet. 0 means global context.
@@ -59,7 +60,7 @@ bool common_encryption_on(struct smb_trans_enc_state *es)
output, so cope with the same for compatibility.
******************************************************************************/
-NTSTATUS common_ntlm_decrypt_buffer(NTLMSSP_STATE *ntlmssp_state, char *buf)
+NTSTATUS common_ntlm_decrypt_buffer(struct ntlmssp_state *ntlmssp_state, char *buf)
{
NTSTATUS status;
size_t buf_len = smb_len(buf) + 4; /* Don't forget the 4 length bytes. */
@@ -107,7 +108,7 @@ NTSTATUS common_ntlm_decrypt_buffer(NTLMSSP_STATE *ntlmssp_state, char *buf)
output, so do the same for compatibility.
******************************************************************************/
-NTSTATUS common_ntlm_encrypt_buffer(NTLMSSP_STATE *ntlmssp_state,
+NTSTATUS common_ntlm_encrypt_buffer(struct ntlmssp_state *ntlmssp_state,
uint16 enc_ctx_num,
char *buf,
char **ppbuf_out)