diff options
author | Nadezhda Ivanova <nadezhda.ivanova@postpath.com> | 2010-01-04 11:24:10 +0200 |
---|---|---|
committer | Nadezhda Ivanova <nadezhda.ivanova@postpath.com> | 2010-01-04 11:24:10 +0200 |
commit | fb5383c69ee52fb5e6d066a43451dc8c806cc795 (patch) | |
tree | 45b72e03f68ab6d212755c524f8e8a60a3b4373a /source3/libsmb | |
parent | 60d8ab3b7b0bd2c9b633f0380d1fdf5bcf5e2621 (diff) | |
parent | a06e5cdb99ddf7abf16486d3837105ec4e0da9ee (diff) | |
download | samba-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.c | 219 | ||||
-rw-r--r-- | source3/libsmb/cliconnect.c | 943 | ||||
-rw-r--r-- | source3/libsmb/clidfs.c | 6 | ||||
-rw-r--r-- | source3/libsmb/clifsinfo.c | 1 | ||||
-rw-r--r-- | source3/libsmb/conncache.c | 82 | ||||
-rw-r--r-- | source3/libsmb/errormap.c | 6 | ||||
-rw-r--r-- | source3/libsmb/libsmb_cache.c | 4 | ||||
-rw-r--r-- | source3/libsmb/ntlmssp.c | 88 | ||||
-rw-r--r-- | source3/libsmb/ntlmssp_ndr.c | 145 | ||||
-rw-r--r-- | source3/libsmb/ntlmssp_ndr.h | 44 | ||||
-rw-r--r-- | source3/libsmb/ntlmssp_sign.c | 53 | ||||
-rw-r--r-- | source3/libsmb/smb_seal.c | 5 |
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) |