X-Git-Url: http://git.samba.org/?a=blobdiff_plain;f=source3%2Flibsmb%2Fclifsinfo.c;h=ff15624c60276f2f1bf02881e8a17646869a8563;hb=6391fff9dad8a2bd7033930e7d6ff5c8617701c6;hp=5e73b61cd20e77435d5eaecb6e23521337a61435;hpb=e8c7ff3e880c7c7e696c5ba7baa8536b4ea7cb89;p=mat%2Fsamba.git diff --git a/source3/libsmb/clifsinfo.c b/source3/libsmb/clifsinfo.c index 5e73b61cd2..ff15624c60 100644 --- a/source3/libsmb/clifsinfo.c +++ b/source3/libsmb/clifsinfo.c @@ -3,354 +3,570 @@ FS info functions Copyright (C) Stefan (metze) Metzmacher 2003 Copyright (C) Jeremy Allison 2007 - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "includes.h" +#include "libsmb/libsmb.h" +#include "../libcli/auth/spnego.h" +#include "../auth/ntlmssp/ntlmssp.h" +#include "../lib/util/tevent_ntstatus.h" +#include "async_smb.h" +#include "../libcli/smb/smb_seal.h" +#include "trans2.h" +#include "ntlmssp_wrap.h" +#include "auth/gensec/gensec.h" +#include "../libcli/smb/smbXcli_base.h" /**************************************************************************** Get UNIX extensions version info. ****************************************************************************/ -bool cli_unix_extensions_version(struct cli_state *cli, uint16 *pmajor, uint16 *pminor, - uint32 *pcaplow, uint32 *pcaphigh) -{ - bool ret = False; - uint16 setup; - char param[2]; - char *rparam=NULL, *rdata=NULL; - unsigned int rparam_count=0, rdata_count=0; +struct cli_unix_extensions_version_state { + struct cli_state *cli; + uint16_t setup[1]; + uint8_t param[2]; + uint16_t major, minor; + uint32_t caplow, caphigh; +}; - setup = TRANSACT2_QFSINFO; +static void cli_unix_extensions_version_done(struct tevent_req *subreq); - SSVAL(param,0,SMB_QUERY_CIFS_UNIX_INFO); +struct tevent_req *cli_unix_extensions_version_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct cli_state *cli) +{ + struct tevent_req *req, *subreq; + struct cli_unix_extensions_version_state *state; - if (!cli_send_trans(cli, SMBtrans2, - NULL, - 0, 0, - &setup, 1, 0, - param, 2, 0, - NULL, 0, 560)) { - goto cleanup; + req = tevent_req_create(mem_ctx, &state, + struct cli_unix_extensions_version_state); + if (req == NULL) { + return NULL; } + state->cli = cli; + SSVAL(state->setup, 0, TRANSACT2_QFSINFO); + SSVAL(state->param, 0, SMB_QUERY_CIFS_UNIX_INFO); - if (!cli_receive_trans(cli, SMBtrans2, - &rparam, &rparam_count, - &rdata, &rdata_count)) { - goto cleanup; + subreq = cli_trans_send(state, ev, cli, SMBtrans2, + NULL, 0, 0, 0, + state->setup, 1, 0, + state->param, 2, 0, + NULL, 0, 560); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); } + tevent_req_set_callback(subreq, cli_unix_extensions_version_done, req); + return req; +} - if (cli_is_error(cli)) { - ret = False; - goto cleanup; - } else { - ret = True; +static void cli_unix_extensions_version_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct cli_unix_extensions_version_state *state = tevent_req_data( + req, struct cli_unix_extensions_version_state); + uint8_t *data; + uint32_t num_data; + NTSTATUS status; + + status = cli_trans_recv(subreq, state, NULL, NULL, 0, NULL, + NULL, 0, NULL, &data, 12, &num_data); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + tevent_req_nterror(req, status); + return; } - if (rdata_count < 12) { - goto cleanup; + state->major = SVAL(data, 0); + state->minor = SVAL(data, 2); + state->caplow = IVAL(data, 4); + state->caphigh = IVAL(data, 8); + TALLOC_FREE(data); + tevent_req_done(req); +} + +NTSTATUS cli_unix_extensions_version_recv(struct tevent_req *req, + uint16_t *pmajor, uint16_t *pminor, + uint32_t *pcaplow, + uint32_t *pcaphigh) +{ + struct cli_unix_extensions_version_state *state = tevent_req_data( + req, struct cli_unix_extensions_version_state); + NTSTATUS status; + + if (tevent_req_is_nterror(req, &status)) { + return status; + } + *pmajor = state->major; + *pminor = state->minor; + *pcaplow = state->caplow; + *pcaphigh = state->caphigh; + state->cli->server_posix_capabilities = *pcaplow; + return NT_STATUS_OK; +} + +NTSTATUS cli_unix_extensions_version(struct cli_state *cli, uint16 *pmajor, + uint16 *pminor, uint32 *pcaplow, + uint32 *pcaphigh) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct event_context *ev; + struct tevent_req *req; + NTSTATUS status = NT_STATUS_OK; + + if (cli_has_async_calls(cli)) { + /* + * Can't use sync call while an async call is in flight + */ + status = NT_STATUS_INVALID_PARAMETER; + goto fail; } - *pmajor = SVAL(rdata,0); - *pminor = SVAL(rdata,2); - cli->posix_capabilities = *pcaplow = IVAL(rdata,4); - *pcaphigh = IVAL(rdata,8); + ev = event_context_init(frame); + if (ev == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } - /* todo: but not yet needed - * return the other stuff - */ + req = cli_unix_extensions_version_send(frame, ev, cli); + if (req == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } -cleanup: - SAFE_FREE(rparam); - SAFE_FREE(rdata); + if (!tevent_req_poll(req, ev)) { + status = map_nt_error_from_unix(errno); + goto fail; + } - return ret; + status = cli_unix_extensions_version_recv(req, pmajor, pminor, pcaplow, + pcaphigh); + fail: + TALLOC_FREE(frame); + return status; } /**************************************************************************** Set UNIX extensions capabilities. ****************************************************************************/ -bool cli_set_unix_extensions_capabilities(struct cli_state *cli, uint16 major, uint16 minor, - uint32 caplow, uint32 caphigh) -{ - bool ret = False; - uint16 setup; - char param[4]; - char data[12]; - char *rparam=NULL, *rdata=NULL; - unsigned int rparam_count=0, rdata_count=0; - - setup = TRANSACT2_SETFSINFO; +struct cli_set_unix_extensions_capabilities_state { + struct cli_state *cli; + uint16_t setup[1]; + uint8_t param[4]; + uint8_t data[12]; +}; - SSVAL(param,0,0); - SSVAL(param,2,SMB_SET_CIFS_UNIX_INFO); +static void cli_set_unix_extensions_capabilities_done( + struct tevent_req *subreq); - SSVAL(data,0,major); - SSVAL(data,2,minor); - SIVAL(data,4,caplow); - SIVAL(data,8,caphigh); +struct tevent_req *cli_set_unix_extensions_capabilities_send( + TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli, + uint16_t major, uint16_t minor, uint32_t caplow, uint32_t caphigh) +{ + struct tevent_req *req, *subreq; + struct cli_set_unix_extensions_capabilities_state *state; - if (!cli_send_trans(cli, SMBtrans2, - NULL, - 0, 0, - &setup, 1, 0, - param, 4, 0, - data, 12, 560)) { - goto cleanup; + req = tevent_req_create( + mem_ctx, &state, + struct cli_set_unix_extensions_capabilities_state); + if (req == NULL) { + return NULL; } - if (!cli_receive_trans(cli, SMBtrans2, - &rparam, &rparam_count, - &rdata, &rdata_count)) { - goto cleanup; - } + state->cli = cli; + SSVAL(state->setup+0, 0, TRANSACT2_SETFSINFO); - if (cli_is_error(cli)) { - ret = False; - goto cleanup; - } else { - ret = True; - } + SSVAL(state->param, 0, 0); + SSVAL(state->param, 2, SMB_SET_CIFS_UNIX_INFO); -cleanup: - SAFE_FREE(rparam); - SAFE_FREE(rdata); + SSVAL(state->data, 0, major); + SSVAL(state->data, 2, minor); + SIVAL(state->data, 4, caplow); + SIVAL(state->data, 8, caphigh); - return ret; + subreq = cli_trans_send(state, ev, cli, SMBtrans2, + NULL, 0, 0, 0, + state->setup, 1, 0, + state->param, 4, 0, + state->data, 12, 560); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback( + subreq, cli_set_unix_extensions_capabilities_done, req); + return req; } -bool cli_get_fs_attr_info(struct cli_state *cli, uint32 *fs_attr) +static void cli_set_unix_extensions_capabilities_done( + struct tevent_req *subreq) { - bool ret = False; - uint16 setup; - char param[2]; - char *rparam=NULL, *rdata=NULL; - unsigned int rparam_count=0, rdata_count=0; + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct cli_set_unix_extensions_capabilities_state *state = tevent_req_data( + req, struct cli_set_unix_extensions_capabilities_state); - if (!cli||!fs_attr) - smb_panic("cli_get_fs_attr_info() called with NULL Pionter!"); + NTSTATUS status = cli_trans_recv(subreq, NULL, NULL, NULL, 0, NULL, + NULL, 0, NULL, NULL, 0, NULL); + if (NT_STATUS_IS_OK(status)) { + state->cli->requested_posix_capabilities = IVAL(state->data, 4); + } + tevent_req_simple_finish_ntstatus(subreq, status); +} - setup = TRANSACT2_QFSINFO; +NTSTATUS cli_set_unix_extensions_capabilities_recv(struct tevent_req *req) +{ + return tevent_req_simple_recv_ntstatus(req); +} - SSVAL(param,0,SMB_QUERY_FS_ATTRIBUTE_INFO); +NTSTATUS cli_set_unix_extensions_capabilities(struct cli_state *cli, + uint16 major, uint16 minor, + uint32 caplow, uint32 caphigh) +{ + struct tevent_context *ev; + struct tevent_req *req; + NTSTATUS status = NT_STATUS_NO_MEMORY; - if (!cli_send_trans(cli, SMBtrans2, - NULL, - 0, 0, - &setup, 1, 0, - param, 2, 0, - NULL, 0, 560)) { - goto cleanup; + if (cli_has_async_calls(cli)) { + return NT_STATUS_INVALID_PARAMETER; } - - if (!cli_receive_trans(cli, SMBtrans2, - &rparam, &rparam_count, - &rdata, &rdata_count)) { - goto cleanup; + ev = tevent_context_init(talloc_tos()); + if (ev == NULL) { + goto fail; } - - if (cli_is_error(cli)) { - ret = False; - goto cleanup; - } else { - ret = True; + req = cli_set_unix_extensions_capabilities_send( + ev, ev, cli, major, minor, caplow, caphigh); + if (req == NULL) { + goto fail; } - - if (rdata_count < 12) { - goto cleanup; + if (!tevent_req_poll_ntstatus(req, ev, &status)) { + goto fail; } - - *fs_attr = IVAL(rdata,0); - - /* todo: but not yet needed - * return the other stuff - */ - -cleanup: - SAFE_FREE(rparam); - SAFE_FREE(rdata); - - return ret; + status = cli_set_unix_extensions_capabilities_recv(req); +fail: + TALLOC_FREE(ev); + return status; } -bool cli_get_fs_volume_info_old(struct cli_state *cli, fstring volume_name, uint32 *pserial_number) -{ - bool ret = False; - uint16 setup; - char param[2]; - char *rparam=NULL, *rdata=NULL; - unsigned int rparam_count=0, rdata_count=0; - unsigned char nlen; +struct cli_get_fs_attr_info_state { + uint16_t setup[1]; + uint8_t param[2]; + uint32_t fs_attr; +}; - setup = TRANSACT2_QFSINFO; +static void cli_get_fs_attr_info_done(struct tevent_req *subreq); - SSVAL(param,0,SMB_INFO_VOLUME); +struct tevent_req *cli_get_fs_attr_info_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct cli_state *cli) +{ + struct tevent_req *subreq, *req; + struct cli_get_fs_attr_info_state *state; - if (!cli_send_trans(cli, SMBtrans2, - NULL, - 0, 0, - &setup, 1, 0, - param, 2, 0, - NULL, 0, 560)) { - goto cleanup; + req = tevent_req_create(mem_ctx, &state, + struct cli_get_fs_attr_info_state); + if (req == NULL) { + return NULL; } + SSVAL(state->setup+0, 0, TRANSACT2_QFSINFO); + SSVAL(state->param+0, 0, SMB_QUERY_FS_ATTRIBUTE_INFO); - if (!cli_receive_trans(cli, SMBtrans2, - &rparam, &rparam_count, - &rdata, &rdata_count)) { - goto cleanup; + subreq = cli_trans_send(state, ev, cli, SMBtrans2, + NULL, 0, 0, 0, + state->setup, 1, 0, + state->param, 2, 0, + NULL, 0, 560); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); } + tevent_req_set_callback(subreq, cli_get_fs_attr_info_done, req); + return req; +} - if (cli_is_error(cli)) { - ret = False; - goto cleanup; - } else { - ret = True; +static void cli_get_fs_attr_info_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct cli_get_fs_attr_info_state *state = tevent_req_data( + req, struct cli_get_fs_attr_info_state); + uint8_t *data; + uint32_t num_data; + NTSTATUS status; + + status = cli_trans_recv(subreq, talloc_tos(), NULL, NULL, 0, NULL, + NULL, 0, NULL, &data, 12, &num_data); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + tevent_req_nterror(req, status); + return; } + state->fs_attr = IVAL(data, 0); + TALLOC_FREE(data); + tevent_req_done(req); +} - if (rdata_count < 5) { - goto cleanup; - } +NTSTATUS cli_get_fs_attr_info_recv(struct tevent_req *req, uint32_t *fs_attr) +{ + struct cli_get_fs_attr_info_state *state = tevent_req_data( + req, struct cli_get_fs_attr_info_state); + NTSTATUS status; - if (pserial_number) { - *pserial_number = IVAL(rdata,0); + if (tevent_req_is_nterror(req, &status)) { + return status; } - nlen = CVAL(rdata,l2_vol_cch); - clistr_pull(cli, volume_name, rdata + l2_vol_szVolLabel, sizeof(fstring), nlen, STR_NOALIGN); - - /* todo: but not yet needed - * return the other stuff - */ + *fs_attr = state->fs_attr; + return NT_STATUS_OK; +} -cleanup: - SAFE_FREE(rparam); - SAFE_FREE(rdata); +NTSTATUS cli_get_fs_attr_info(struct cli_state *cli, uint32_t *fs_attr) +{ + struct tevent_context *ev; + struct tevent_req *req; + NTSTATUS status = NT_STATUS_NO_MEMORY; - return ret; + if (cli_has_async_calls(cli)) { + return NT_STATUS_INVALID_PARAMETER; + } + ev = tevent_context_init(talloc_tos()); + if (ev == NULL) { + goto fail; + } + req = cli_get_fs_attr_info_send(ev, ev, cli); + if (req == NULL) { + goto fail; + } + if (!tevent_req_poll_ntstatus(req, ev, &status)) { + goto fail; + } + status = cli_get_fs_attr_info_recv(req, fs_attr); +fail: + TALLOC_FREE(ev); + return status; } -bool cli_get_fs_volume_info(struct cli_state *cli, fstring volume_name, uint32 *pserial_number, time_t *pdate) +NTSTATUS cli_get_fs_volume_info(struct cli_state *cli, + TALLOC_CTX *mem_ctx, + char **_volume_name, + uint32_t *pserial_number, + time_t *pdate) { - bool ret = False; - uint16 setup; - char param[2]; - char *rparam=NULL, *rdata=NULL; - unsigned int rparam_count=0, rdata_count=0; + NTSTATUS status; + uint16_t recv_flags2; + uint16_t setup[1]; + uint8_t param[2]; + uint8_t *rdata; + uint32_t rdata_count; unsigned int nlen; + char *volume_name = NULL; - setup = TRANSACT2_QFSINFO; - + SSVAL(setup, 0, TRANSACT2_QFSINFO); SSVAL(param,0,SMB_QUERY_FS_VOLUME_INFO); - if (!cli_send_trans(cli, SMBtrans2, - NULL, - 0, 0, - &setup, 1, 0, - param, 2, 0, - NULL, 0, 560)) { - goto cleanup; - } - - if (!cli_receive_trans(cli, SMBtrans2, - &rparam, &rparam_count, - &rdata, &rdata_count)) { - goto cleanup; - } - - if (cli_is_error(cli)) { - ret = False; - goto cleanup; - } else { - ret = True; - } - - if (rdata_count < 19) { - goto cleanup; + status = cli_trans(talloc_tos(), cli, SMBtrans2, + NULL, 0, 0, 0, + setup, 1, 0, + param, 2, 0, + NULL, 0, 560, + &recv_flags2, + NULL, 0, NULL, + NULL, 0, NULL, + &rdata, 18, &rdata_count); + if (!NT_STATUS_IS_OK(status)) { + return status; } if (pdate) { struct timespec ts; - ts = interpret_long_date(rdata); + ts = interpret_long_date((char *)rdata); *pdate = ts.tv_sec; } if (pserial_number) { *pserial_number = IVAL(rdata,8); } nlen = IVAL(rdata,12); - clistr_pull(cli, volume_name, rdata + 18, sizeof(fstring), nlen, STR_UNICODE); + if (nlen > (rdata_count - 18)) { + TALLOC_FREE(rdata); + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + + clistr_pull_talloc(mem_ctx, + (const char *)rdata, + recv_flags2, + &volume_name, + rdata + 18, + nlen, STR_UNICODE); + if (volume_name == NULL) { + status = map_nt_error_from_unix(errno); + TALLOC_FREE(rdata); + return status; + } /* todo: but not yet needed * return the other stuff */ -cleanup: - SAFE_FREE(rparam); - SAFE_FREE(rdata); + *_volume_name = volume_name; + TALLOC_FREE(rdata); + return NT_STATUS_OK; +} + +NTSTATUS cli_get_fs_full_size_info(struct cli_state *cli, + uint64_t *total_allocation_units, + uint64_t *caller_allocation_units, + uint64_t *actual_allocation_units, + uint64_t *sectors_per_allocation_unit, + uint64_t *bytes_per_sector) +{ + uint16 setup[1]; + uint8_t param[2]; + uint8_t *rdata = NULL; + uint32_t rdata_count; + NTSTATUS status; + + SSVAL(setup, 0, TRANSACT2_QFSINFO); + SSVAL(param, 0, SMB_FS_FULL_SIZE_INFORMATION); + + status = cli_trans(talloc_tos(), cli, SMBtrans2, + NULL, 0, 0, 0, + setup, 1, 0, /* setup */ + param, 2, 0, /* param */ + NULL, 0, 560, /* data */ + NULL, + NULL, 0, NULL, /* rsetup */ + NULL, 0, NULL, /* rparam */ + &rdata, 32, &rdata_count); /* rdata */ + if (!NT_STATUS_IS_OK(status)) { + goto fail; + } - return ret; + if (total_allocation_units) { + *total_allocation_units = BIG_UINT(rdata, 0); + } + if (caller_allocation_units) { + *caller_allocation_units = BIG_UINT(rdata,8); + } + if (actual_allocation_units) { + *actual_allocation_units = BIG_UINT(rdata,16); + } + if (sectors_per_allocation_unit) { + *sectors_per_allocation_unit = IVAL(rdata,24); + } + if (bytes_per_sector) { + *bytes_per_sector = IVAL(rdata,28); + } + +fail: + TALLOC_FREE(rdata); + return status; +} + +NTSTATUS cli_get_posix_fs_info(struct cli_state *cli, + uint32 *optimal_transfer_size, + uint32 *block_size, + uint64_t *total_blocks, + uint64_t *blocks_available, + uint64_t *user_blocks_available, + uint64_t *total_file_nodes, + uint64_t *free_file_nodes, + uint64_t *fs_identifier) +{ + uint16 setup[1]; + uint8_t param[2]; + uint8_t *rdata = NULL; + uint32_t rdata_count; + NTSTATUS status; + + SSVAL(setup, 0, TRANSACT2_QFSINFO); + SSVAL(param,0,SMB_QUERY_POSIX_FS_INFO); + + status = cli_trans(talloc_tos(), cli, SMBtrans2, NULL, 0, 0, 0, + setup, 1, 0, + param, 2, 0, + NULL, 0, 560, + NULL, + NULL, 0, NULL, /* rsetup */ + NULL, 0, NULL, /* rparam */ + &rdata, 56, &rdata_count); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + if (optimal_transfer_size) { + *optimal_transfer_size = IVAL(rdata, 0); + } + if (block_size) { + *block_size = IVAL(rdata,4); + } + if (total_blocks) { + *total_blocks = BIG_UINT(rdata,8); + } + if (blocks_available) { + *blocks_available = BIG_UINT(rdata,16); + } + if (user_blocks_available) { + *user_blocks_available = BIG_UINT(rdata,24); + } + if (total_file_nodes) { + *total_file_nodes = BIG_UINT(rdata,32); + } + if (free_file_nodes) { + *free_file_nodes = BIG_UINT(rdata,40); + } + if (fs_identifier) { + *fs_identifier = BIG_UINT(rdata,48); + } + return NT_STATUS_OK; } + /****************************************************************************** Send/receive the request encryption blob. ******************************************************************************/ static NTSTATUS enc_blob_send_receive(struct cli_state *cli, DATA_BLOB *in, DATA_BLOB *out, DATA_BLOB *param_out) { - uint16 setup; - char param[4]; - char *rparam=NULL, *rdata=NULL; - unsigned int rparam_count=0, rdata_count=0; - NTSTATUS status = NT_STATUS_OK; - - setup = TRANSACT2_SETFSINFO; + uint16_t setup[1]; + uint8_t param[4]; + uint8_t *rparam=NULL, *rdata=NULL; + uint32_t num_rparam, num_rdata; + NTSTATUS status; + SSVAL(setup+0, 0, TRANSACT2_SETFSINFO); SSVAL(param,0,0); SSVAL(param,2,SMB_REQUEST_TRANSPORT_ENCRYPTION); - if (!cli_send_trans(cli, SMBtrans2, - NULL, - 0, 0, - &setup, 1, 0, - param, 4, 0, - (char *)in->data, in->length, CLI_BUFFER_SIZE)) { - status = cli_nt_error(cli); - goto out; - } - - if (!cli_receive_trans(cli, SMBtrans2, - &rparam, &rparam_count, - &rdata, &rdata_count)) { - status = cli_nt_error(cli); - goto out; - } + status = cli_trans(talloc_tos(), cli, SMBtrans2, NULL, 0, 0, 0, + setup, 1, 0, + param, 4, 2, + (uint8_t *)in->data, in->length, CLI_BUFFER_SIZE, + NULL, /* recv_flags */ + NULL, 0, NULL, /* rsetup */ + &rparam, 0, &num_rparam, + &rdata, 0, &num_rdata); - if (cli_is_error(cli)) { - status = cli_nt_error(cli); - if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { - goto out; - } + if (!NT_STATUS_IS_OK(status) && + !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { + return status; } - *out = data_blob(rdata, rdata_count); - *param_out = data_blob(rparam, rparam_count); + *out = data_blob(rdata, num_rdata); + *param_out = data_blob(rparam, num_rparam); - out: - - SAFE_FREE(rparam); - SAFE_FREE(rdata); + TALLOC_FREE(rparam); + TALLOC_FREE(rdata); return status; } @@ -394,31 +610,38 @@ NTSTATUS cli_raw_ntlm_smb_encryption_start(struct cli_state *cli, DATA_BLOB blob_out = data_blob_null; DATA_BLOB param_out = data_blob_null; NTSTATUS status = NT_STATUS_UNSUCCESSFUL; + struct auth_generic_state *auth_ntlmssp_state; struct smb_trans_enc_state *es = make_cli_enc_state(SMB_TRANS_ENC_NTLM); if (!es) { return NT_STATUS_NO_MEMORY; } - status = ntlmssp_client_start(&es->s.ntlmssp_state); + status = auth_ntlmssp_client_prepare(NULL, + &auth_ntlmssp_state); if (!NT_STATUS_IS_OK(status)) { goto fail; } - ntlmssp_want_feature(es->s.ntlmssp_state, NTLMSSP_FEATURE_SESSION_KEY); - es->s.ntlmssp_state->neg_flags |= (NTLMSSP_NEGOTIATE_SIGN|NTLMSSP_NEGOTIATE_SEAL); + gensec_want_feature(auth_ntlmssp_state->gensec_security, GENSEC_FEATURE_SESSION_KEY); + gensec_want_feature(auth_ntlmssp_state->gensec_security, GENSEC_FEATURE_SEAL); - if (!NT_STATUS_IS_OK(status = ntlmssp_set_username(es->s.ntlmssp_state, user))) { + if (!NT_STATUS_IS_OK(status = auth_ntlmssp_set_username(auth_ntlmssp_state, user))) { + goto fail; + } + if (!NT_STATUS_IS_OK(status = auth_ntlmssp_set_domain(auth_ntlmssp_state, domain))) { goto fail; } - if (!NT_STATUS_IS_OK(status = ntlmssp_set_domain(es->s.ntlmssp_state, domain))) { + if (!NT_STATUS_IS_OK(status = auth_ntlmssp_set_password(auth_ntlmssp_state, pass))) { goto fail; } - if (!NT_STATUS_IS_OK(status = ntlmssp_set_password(es->s.ntlmssp_state, pass))) { + + if (!NT_STATUS_IS_OK(status = auth_ntlmssp_client_start(auth_ntlmssp_state))) { goto fail; } do { - status = ntlmssp_update(es->s.ntlmssp_state, blob_in, &blob_out); + status = gensec_update(auth_ntlmssp_state->gensec_security, auth_ntlmssp_state, + NULL, blob_in, &blob_out); data_blob_free(&blob_in); data_blob_free(¶m_out); if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) || NT_STATUS_IS_OK(status)) { @@ -442,17 +665,19 @@ NTSTATUS cli_raw_ntlm_smb_encryption_start(struct cli_state *cli, data_blob_free(&blob_in); if (NT_STATUS_IS_OK(status)) { + es->enc_on = true; /* Replace the old state, if any. */ - if (cli->trans_enc_state) { - common_free_encryption_state(&cli->trans_enc_state); - } - cli->trans_enc_state = es; - cli->trans_enc_state->enc_on = True; + /* We only need the gensec_security part from here. + * es is a malloc()ed pointer, so we cannot make + * gensec_security a talloc child */ + es->s.gensec_security = talloc_move(NULL, + &auth_ntlmssp_state->gensec_security); + smb1cli_conn_set_encryption(cli->conn, es); es = NULL; } fail: - + TALLOC_FREE(auth_ntlmssp_state); common_free_encryption_state(&es); return status; } @@ -467,7 +692,8 @@ NTSTATUS cli_raw_ntlm_smb_encryption_start(struct cli_state *cli, Get client gss blob to send to a server. ******************************************************************************/ -static NTSTATUS make_cli_gss_blob(struct smb_trans_enc_state *es, +static NTSTATUS make_cli_gss_blob(TALLOC_CTX *ctx, + struct smb_trans_enc_state *es, const char *service, const char *host, NTSTATUS status_in, @@ -488,7 +714,7 @@ static NTSTATUS make_cli_gss_blob(struct smb_trans_enc_state *es, NTSTATUS status = NT_STATUS_OK; gss_OID_desc nt_hostbased_service = - {10, CONST_DISCARD(char *,"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x04")}; + {10, discard_const_p(char, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x04")}; memset(&tok_out, '\0', sizeof(tok_out)); @@ -514,7 +740,7 @@ static NTSTATUS make_cli_gss_blob(struct smb_trans_enc_state *es, p_tok_in = GSS_C_NO_BUFFER; } else { /* Remove the SPNEGO wrapper */ - if (!spnego_parse_auth_response(spnego_blob_in, status_in, OID_KERBEROS5, &blob_in)) { + if (!spnego_parse_auth_response(ctx, spnego_blob_in, status_in, OID_KERBEROS5, &blob_in)) { status = NT_STATUS_UNSUCCESSFUL; goto fail; } @@ -549,10 +775,10 @@ static NTSTATUS make_cli_gss_blob(struct smb_trans_enc_state *es, status = NT_STATUS_ACCESS_DENIED; } - blob_out = data_blob(tok_out.value, tok_out.length); + blob_out = data_blob_talloc(ctx, tok_out.value, tok_out.length); /* Wrap in an SPNEGO wrapper */ - *p_blob_out = gen_negTokenTarg(krb_mechs, blob_out); + *p_blob_out = spnego_gen_negTokenInit(ctx, krb_mechs, &blob_out, NULL); fail: @@ -584,14 +810,14 @@ NTSTATUS cli_gss_smb_encryption_start(struct cli_state *cli) return NT_STATUS_NO_MEMORY; } - name_to_fqdn(fqdn, cli->desthost); + name_to_fqdn(fqdn, cli_state_remote_name(cli)); strlower_m(fqdn); servicename = "cifs"; - status = make_cli_gss_blob(es, servicename, fqdn, NT_STATUS_OK, blob_recv, &blob_send); + status = make_cli_gss_blob(talloc_tos(), es, servicename, fqdn, NT_STATUS_OK, blob_recv, &blob_send); if (!NT_STATUS_EQUAL(status,NT_STATUS_MORE_PROCESSING_REQUIRED)) { servicename = "host"; - status = make_cli_gss_blob(es, servicename, fqdn, NT_STATUS_OK, blob_recv, &blob_send); + status = make_cli_gss_blob(talloc_tos(), es, servicename, fqdn, NT_STATUS_OK, blob_recv, &blob_send); if (!NT_STATUS_EQUAL(status,NT_STATUS_MORE_PROCESSING_REQUIRED)) { goto fail; } @@ -604,17 +830,14 @@ NTSTATUS cli_gss_smb_encryption_start(struct cli_state *cli) es->enc_ctx_num = SVAL(param_out.data, 0); } data_blob_free(&blob_send); - status = make_cli_gss_blob(es, servicename, fqdn, status, blob_recv, &blob_send); + status = make_cli_gss_blob(talloc_tos(), es, servicename, fqdn, status, blob_recv, &blob_send); } while (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)); data_blob_free(&blob_recv); if (NT_STATUS_IS_OK(status)) { + es->enc_on = true; /* Replace the old state, if any. */ - if (cli->trans_enc_state) { - common_free_encryption_state(&cli->trans_enc_state); - } - cli->trans_enc_state = es; - cli->trans_enc_state->enc_on = True; + smb1cli_conn_set_encryption(cli->conn, es); es = NULL; } @@ -641,12 +864,17 @@ NTSTATUS cli_force_encryption(struct cli_state *c, { uint16 major, minor; uint32 caplow, caphigh; + NTSTATUS status; if (!SERVER_HAS_UNIX_CIFS(c)) { return NT_STATUS_NOT_SUPPORTED; } - if (!cli_unix_extensions_version(c, &major, &minor, &caplow, &caphigh)) { + status = cli_unix_extensions_version(c, &major, &minor, &caplow, + &caphigh); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("cli_force_encryption: cli_unix_extensions_version " + "returned %s\n", nt_errstr(status))); return NT_STATUS_UNKNOWN_REVISION; }