1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-24 21:34:56 +03:00
samba-mirror/libcli/smb/smb1cli_session.c

260 lines
6.6 KiB
C
Raw Normal View History

/*
Unix SMB/CIFS implementation.
client connect/disconnect routines
Copyright (C) Andrew Tridgell 1994-1998
Copyright (C) Andrew Bartlett 2001-2003
Copyright (C) Volker Lendecke 2011
Copyright (C) Jeremy Allison 2011
Copyright (C) Stefan Metzmacher 2016
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 "system/network.h"
#include "../lib/util/tevent_ntstatus.h"
#include "../libcli/smb/smb_common.h"
#include "../libcli/smb/smbXcli_base.h"
struct smb1cli_session_setup_lm21_state {
struct smbXcli_session *session;
uint16_t vwv[10];
struct iovec *recv_iov;
uint16_t out_session_id;
uint16_t out_action;
char *out_native_os;
char *out_native_lm;
};
static void smb1cli_session_setup_lm21_done(struct tevent_req *subreq);
struct tevent_req *smb1cli_session_setup_lm21_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct smbXcli_conn *conn,
uint32_t timeout_msec,
uint32_t pid,
struct smbXcli_session *session,
uint16_t in_buf_size,
uint16_t in_mpx_max,
uint16_t in_vc_num,
uint32_t in_sess_key,
const char *in_user,
const char *in_domain,
const DATA_BLOB in_apassword,
const char *in_native_os,
const char *in_native_lm)
{
struct tevent_req *req = NULL;
struct smb1cli_session_setup_lm21_state *state = NULL;
struct tevent_req *subreq = NULL;
uint16_t *vwv = NULL;
uint8_t *bytes = NULL;
req = tevent_req_create(mem_ctx, &state,
struct smb1cli_session_setup_lm21_state);
if (req == NULL) {
return NULL;
}
state->session = session;
vwv = state->vwv;
if (in_user == NULL) {
tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
return tevent_req_post(req, ev);
}
if (in_domain == NULL) {
tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
return tevent_req_post(req, ev);
}
if (in_apassword.length > UINT16_MAX) {
tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
return tevent_req_post(req, ev);
}
if (in_native_os == NULL && in_native_lm != NULL) {
tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
return tevent_req_post(req, ev);
}
SCVAL(vwv+0, 0, 0xff);
SCVAL(vwv+0, 1, 0);
SSVAL(vwv+1, 0, 0);
SSVAL(vwv+2, 0, in_buf_size);
SSVAL(vwv+3, 0, in_mpx_max);
SSVAL(vwv+4, 0, in_vc_num);
SIVAL(vwv+5, 0, in_sess_key);
SSVAL(vwv+7, 0, in_apassword.length);
SSVAL(vwv+8, 0, 0); /* reserved */
SSVAL(vwv+9, 0, 0); /* reserved */
bytes = talloc_array(state, uint8_t,
in_apassword.length);
if (tevent_req_nomem(bytes, req)) {
return tevent_req_post(req, ev);
}
if (in_apassword.length != 0) {
memcpy(bytes,
in_apassword.data,
in_apassword.length);
}
bytes = smb_bytes_push_str(bytes,
smbXcli_conn_use_unicode(conn),
in_user, strlen(in_user)+1,
NULL);
bytes = smb_bytes_push_str(bytes,
smbXcli_conn_use_unicode(conn),
in_domain, strlen(in_domain)+1,
NULL);
if (in_native_os != NULL) {
bytes = smb_bytes_push_str(bytes,
smbXcli_conn_use_unicode(conn),
in_native_os, strlen(in_native_os)+1,
NULL);
}
if (in_native_lm != NULL) {
bytes = smb_bytes_push_str(bytes,
smbXcli_conn_use_unicode(conn),
in_native_lm, strlen(in_native_lm)+1,
NULL);
}
if (tevent_req_nomem(bytes, req)) {
return tevent_req_post(req, ev);
}
subreq = smb1cli_req_send(state, ev, conn,
SMBsesssetupX,
0, /* additional_flags */
0, /* clear_flags */
0, /* additional_flags2 */
0, /* clear_flags2 */
timeout_msec,
pid,
NULL, /* tcon */
session,
10, /* wct */
vwv,
talloc_get_size(bytes),
bytes);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
tevent_req_set_callback(subreq, smb1cli_session_setup_lm21_done, req);
return req;
}
static void smb1cli_session_setup_lm21_done(struct tevent_req *subreq)
{
struct tevent_req *req =
tevent_req_callback_data(subreq,
struct tevent_req);
struct smb1cli_session_setup_lm21_state *state =
tevent_req_data(req,
struct smb1cli_session_setup_lm21_state);
NTSTATUS status;
uint8_t *inhdr = NULL;
uint8_t wct;
uint16_t *vwv = NULL;
uint32_t num_bytes;
uint8_t *bytes = NULL;
const uint8_t *p = NULL;
size_t ret = 0;
uint16_t flags2;
bool use_unicode = false;
struct smb1cli_req_expected_response expected[] = {
{
.status = NT_STATUS_OK,
.wct = 3,
},
};
status = smb1cli_req_recv(subreq, state,
&state->recv_iov,
&inhdr,
&wct,
&vwv,
NULL, /* pvwv_offset */
&num_bytes,
&bytes,
NULL, /* pbytes_offset */
NULL, /* pinbuf */
expected, ARRAY_SIZE(expected));
TALLOC_FREE(subreq);
if (tevent_req_nterror(req, status)) {
return;
}
flags2 = SVAL(inhdr, HDR_FLG2);
if (flags2 & FLAGS2_UNICODE_STRINGS) {
use_unicode = true;
}
state->out_session_id = SVAL(inhdr, HDR_UID);
state->out_action = SVAL(vwv+2, 0);
p = bytes;
status = smb_bytes_pull_str(state, &state->out_native_os,
use_unicode, p,
bytes+num_bytes-p, &ret);
if (tevent_req_nterror(req, status)) {
return;
}
p += ret;
status = smb_bytes_pull_str(state, &state->out_native_lm,
use_unicode, p,
bytes+num_bytes-p, &ret);
if (tevent_req_nterror(req, status)) {
return;
}
p += ret;
smb1cli_session_set_id(state->session, state->out_session_id);
smb1cli_session_set_action(state->session, state->out_action);
tevent_req_done(req);
}
NTSTATUS smb1cli_session_setup_lm21_recv(struct tevent_req *req,
TALLOC_CTX *mem_ctx,
char **out_native_os,
char **out_native_lm)
{
struct smb1cli_session_setup_lm21_state *state =
tevent_req_data(req,
struct smb1cli_session_setup_lm21_state);
NTSTATUS status;
if (tevent_req_is_nterror(req, &status)) {
tevent_req_received(req);
return status;
}
if (out_native_os != NULL) {
*out_native_os = talloc_move(mem_ctx, &state->out_native_os);
}
if (out_native_lm != NULL) {
*out_native_lm = talloc_move(mem_ctx, &state->out_native_lm);
}
tevent_req_received(req);
return NT_STATUS_OK;
}