1
0
mirror of https://github.com/samba-team/samba.git synced 2025-06-23 11:17:06 +03:00
Andrew Tridgell 7cbc768376 r4777: added a smb_composite_sesssetup() async composite function. This
encapsulates all the different session setup methods, including the
multi-pass spnego code.

I have hooked this into all the places that previously used the
RAW_SESSSETUP_GENERIC method, and have removed the old
RAW_SESSSETUP_GENERIC code from clisession.c and clitree.c. A nice
side effect is that these two modules are now very simple again, back
to being "raw" session setup handling, which was what was originally
intended.

I have also used this to replace the session setup code in the
smb_composite_connect() code, and used that to build a very simple
replacement for smbcli_tree_full_connection().

As a result, smbclient, smbtorture and all our other SMB connection
code now goes via these composite async functions. That should give
them a good workout!
(This used to be commit 080d0518bc7d6fd4bc3ef783e7d4d2e3275d0799)
2007-10-10 13:08:53 -05:00

283 lines
9.5 KiB
C

/*
Unix SMB/CIFS implementation.
SMB client session context management functions
Copyright (C) Andrew Tridgell 1994-2005
Copyright (C) James Myers 2003 <myersjj@samba.org>
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 2 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, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "includes.h"
#include "libcli/raw/libcliraw.h"
#include "auth/auth.h"
#define SETUP_REQUEST_SESSION(cmd, wct, buflen) do { \
req = smbcli_request_setup_session(session, cmd, wct, buflen); \
if (!req) return NULL; \
} while (0)
/****************************************************************************
Initialize the session context
****************************************************************************/
struct smbcli_session *smbcli_session_init(struct smbcli_transport *transport)
{
struct smbcli_session *session;
uint16_t flags2;
uint32_t capabilities;
session = talloc_zero(transport, struct smbcli_session);
if (!session) {
return NULL;
}
session->transport = talloc_reference(session, transport);
session->pid = (uint16_t)getpid();
session->vuid = UID_FIELD_INVALID;
capabilities = transport->negotiate.capabilities;
flags2 = FLAGS2_LONG_PATH_COMPONENTS | FLAGS2_EXTENDED_ATTRIBUTES;
if (capabilities & CAP_UNICODE) {
flags2 |= FLAGS2_UNICODE_STRINGS;
}
if (capabilities & CAP_STATUS32) {
flags2 |= FLAGS2_32_BIT_ERROR_CODES;
}
if (capabilities & CAP_EXTENDED_SECURITY) {
flags2 |= FLAGS2_EXTENDED_SECURITY;
}
if (session->transport->negotiate.sign_info.doing_signing) {
flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES;
}
session->flags2 = flags2;
return session;
}
/****************************************************************************
Perform a session setup (async send)
****************************************************************************/
struct smbcli_request *smb_raw_session_setup_send(struct smbcli_session *session, union smb_sesssetup *parms)
{
struct smbcli_request *req = NULL;
switch (parms->old.level) {
case RAW_SESSSETUP_OLD:
SETUP_REQUEST_SESSION(SMBsesssetupX, 10, 0);
SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
SSVAL(req->out.vwv, VWV(1), 0);
SSVAL(req->out.vwv,VWV(2),parms->old.in.bufsize);
SSVAL(req->out.vwv,VWV(3),parms->old.in.mpx_max);
SSVAL(req->out.vwv,VWV(4),parms->old.in.vc_num);
SIVAL(req->out.vwv,VWV(5),parms->old.in.sesskey);
SSVAL(req->out.vwv,VWV(7),parms->old.in.password.length);
SIVAL(req->out.vwv,VWV(8), 0); /* reserved */
smbcli_req_append_blob(req, &parms->old.in.password);
smbcli_req_append_string(req, parms->old.in.user, STR_TERMINATE);
smbcli_req_append_string(req, parms->old.in.domain, STR_TERMINATE|STR_UPPER);
smbcli_req_append_string(req, parms->old.in.os, STR_TERMINATE);
smbcli_req_append_string(req, parms->old.in.lanman, STR_TERMINATE);
break;
case RAW_SESSSETUP_NT1:
SETUP_REQUEST_SESSION(SMBsesssetupX, 13, 0);
SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
SSVAL(req->out.vwv, VWV(1), 0);
SSVAL(req->out.vwv, VWV(2), parms->nt1.in.bufsize);
SSVAL(req->out.vwv, VWV(3), parms->nt1.in.mpx_max);
SSVAL(req->out.vwv, VWV(4), parms->nt1.in.vc_num);
SIVAL(req->out.vwv, VWV(5), parms->nt1.in.sesskey);
SSVAL(req->out.vwv, VWV(7), parms->nt1.in.password1.length);
SSVAL(req->out.vwv, VWV(8), parms->nt1.in.password2.length);
SIVAL(req->out.vwv, VWV(9), 0); /* reserved */
SIVAL(req->out.vwv, VWV(11), parms->nt1.in.capabilities);
smbcli_req_append_blob(req, &parms->nt1.in.password1);
smbcli_req_append_blob(req, &parms->nt1.in.password2);
smbcli_req_append_string(req, parms->nt1.in.user, STR_TERMINATE);
smbcli_req_append_string(req, parms->nt1.in.domain, STR_TERMINATE|STR_UPPER);
smbcli_req_append_string(req, parms->nt1.in.os, STR_TERMINATE);
smbcli_req_append_string(req, parms->nt1.in.lanman, STR_TERMINATE);
break;
case RAW_SESSSETUP_SPNEGO:
SETUP_REQUEST_SESSION(SMBsesssetupX, 12, 0);
SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
SSVAL(req->out.vwv, VWV(1), 0);
SSVAL(req->out.vwv, VWV(2), parms->spnego.in.bufsize);
SSVAL(req->out.vwv, VWV(3), parms->spnego.in.mpx_max);
SSVAL(req->out.vwv, VWV(4), parms->spnego.in.vc_num);
SIVAL(req->out.vwv, VWV(5), parms->spnego.in.sesskey);
SSVAL(req->out.vwv, VWV(7), parms->spnego.in.secblob.length);
SIVAL(req->out.vwv, VWV(8), 0); /* reserved */
SIVAL(req->out.vwv, VWV(10), parms->spnego.in.capabilities);
smbcli_req_append_blob(req, &parms->spnego.in.secblob);
smbcli_req_append_string(req, parms->spnego.in.os, STR_TERMINATE);
smbcli_req_append_string(req, parms->spnego.in.lanman, STR_TERMINATE);
smbcli_req_append_string(req, parms->spnego.in.domain, STR_TERMINATE);
break;
}
if (!smbcli_request_send(req)) {
smbcli_request_destroy(req);
return NULL;
}
return req;
}
/****************************************************************************
Perform a session setup (async recv)
****************************************************************************/
NTSTATUS smb_raw_session_setup_recv(struct smbcli_request *req,
TALLOC_CTX *mem_ctx,
union smb_sesssetup *parms)
{
uint16_t len;
uint8_t *p;
if (!smbcli_request_receive(req)) {
return smbcli_request_destroy(req);
}
if (!NT_STATUS_IS_OK(req->status) &&
!NT_STATUS_EQUAL(req->status,NT_STATUS_MORE_PROCESSING_REQUIRED)) {
return smbcli_request_destroy(req);
}
switch (parms->old.level) {
case RAW_SESSSETUP_OLD:
SMBCLI_CHECK_WCT(req, 3);
ZERO_STRUCT(parms->old.out);
parms->old.out.vuid = SVAL(req->in.hdr, HDR_UID);
parms->old.out.action = SVAL(req->in.vwv, VWV(2));
p = req->in.data;
if (p) {
p += smbcli_req_pull_string(req, mem_ctx, &parms->old.out.os, p, -1, STR_TERMINATE);
p += smbcli_req_pull_string(req, mem_ctx, &parms->old.out.lanman, p, -1, STR_TERMINATE);
p += smbcli_req_pull_string(req, mem_ctx, &parms->old.out.domain, p, -1, STR_TERMINATE);
}
break;
case RAW_SESSSETUP_NT1:
SMBCLI_CHECK_WCT(req, 3);
ZERO_STRUCT(parms->nt1.out);
parms->nt1.out.vuid = SVAL(req->in.hdr, HDR_UID);
parms->nt1.out.action = SVAL(req->in.vwv, VWV(2));
p = req->in.data;
if (p) {
p += smbcli_req_pull_string(req, mem_ctx, &parms->nt1.out.os, p, -1, STR_TERMINATE);
p += smbcli_req_pull_string(req, mem_ctx, &parms->nt1.out.lanman, p, -1, STR_TERMINATE);
if (p < (req->in.data + req->in.data_size)) {
p += smbcli_req_pull_string(req, mem_ctx, &parms->nt1.out.domain, p, -1, STR_TERMINATE);
}
}
break;
case RAW_SESSSETUP_SPNEGO:
SMBCLI_CHECK_WCT(req, 4);
ZERO_STRUCT(parms->spnego.out);
parms->spnego.out.vuid = SVAL(req->in.hdr, HDR_UID);
parms->spnego.out.action = SVAL(req->in.vwv, VWV(2));
len = SVAL(req->in.vwv, VWV(3));
p = req->in.data;
if (!p) {
break;
}
parms->spnego.out.secblob = smbcli_req_pull_blob(req, mem_ctx, p, len);
p += parms->spnego.out.secblob.length;
p += smbcli_req_pull_string(req, mem_ctx, &parms->spnego.out.os, p, -1, STR_TERMINATE);
p += smbcli_req_pull_string(req, mem_ctx, &parms->spnego.out.lanman, p, -1, STR_TERMINATE);
p += smbcli_req_pull_string(req, mem_ctx, &parms->spnego.out.domain, p, -1, STR_TERMINATE);
break;
}
failed:
return smbcli_request_destroy(req);
}
/*
Perform a session setup (sync interface)
*/
NTSTATUS smb_raw_session_setup(struct smbcli_session *session, TALLOC_CTX *mem_ctx,
union smb_sesssetup *parms)
{
struct smbcli_request *req = smb_raw_session_setup_send(session, parms);
return smb_raw_session_setup_recv(req, mem_ctx, parms);
}
/****************************************************************************
Send a uloggoff (async send)
*****************************************************************************/
struct smbcli_request *smb_raw_ulogoff_send(struct smbcli_session *session)
{
struct smbcli_request *req;
SETUP_REQUEST_SESSION(SMBulogoffX, 2, 0);
SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
SSVAL(req->out.vwv, VWV(1), 0);
if (!smbcli_request_send(req)) {
smbcli_request_destroy(req);
return NULL;
}
return req;
}
/****************************************************************************
Send a uloggoff (sync interface)
*****************************************************************************/
NTSTATUS smb_raw_ulogoff(struct smbcli_session *session)
{
struct smbcli_request *req = smb_raw_ulogoff_send(session);
return smbcli_request_simple_recv(req);
}
/****************************************************************************
Send a exit (async send)
*****************************************************************************/
struct smbcli_request *smb_raw_exit_send(struct smbcli_session *session)
{
struct smbcli_request *req;
SETUP_REQUEST_SESSION(SMBexit, 0, 0);
if (!smbcli_request_send(req)) {
smbcli_request_destroy(req);
return NULL;
}
return req;
}
/****************************************************************************
Send a exit (sync interface)
*****************************************************************************/
NTSTATUS smb_raw_exit(struct smbcli_session *session)
{
struct smbcli_request *req = smb_raw_exit_send(session);
return smbcli_request_simple_recv(req);
}