summaryrefslogtreecommitdiffstats
path: root/source4/libcli/raw/clisession.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/libcli/raw/clisession.c')
-rw-r--r--source4/libcli/raw/clisession.c310
1 files changed, 310 insertions, 0 deletions
diff --git a/source4/libcli/raw/clisession.c b/source4/libcli/raw/clisession.c
new file mode 100644
index 0000000..5c3d7f9
--- /dev/null
+++ b/source4/libcli/raw/clisession.c
@@ -0,0 +1,310 @@
+/*
+ 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 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 "libcli/raw/libcliraw.h"
+#include "libcli/raw/raw_proto.h"
+#include "system/filesys.h"
+#include "../libcli/smb/smbXcli_base.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,
+ TALLOC_CTX *parent_ctx, bool primary,
+ struct smbcli_session_options options)
+{
+ struct smbcli_session *session;
+ uint16_t flags2;
+ uint32_t capabilities;
+
+ session = talloc_zero(parent_ctx, struct smbcli_session);
+ if (!session) {
+ return NULL;
+ }
+
+ if (primary) {
+ session->transport = talloc_steal(session, transport);
+ } else {
+ session->transport = talloc_reference(session, transport);
+ }
+ session->pid = (uint32_t)getpid();
+ session->vuid = UID_FIELD_INVALID;
+ session->options = options;
+
+ /*
+ * for now session->vuid is still used by the callers, but we call:
+ * smb1cli_session_set_id(session->smbXcli, session->vuid);
+ * before using session->smbXcli, in future we should remove
+ * session->vuid.
+ */
+ session->smbXcli = smbXcli_session_create(session, transport->conn);
+ if (session->smbXcli == NULL) {
+ talloc_free(session);
+ return NULL;
+ }
+
+ 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 (smb1cli_conn_signing_is_active(session->transport->conn)) {
+ flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES;
+ }
+
+ session->flags2 = flags2;
+
+ return session;
+}
+
+/****************************************************************************
+ Perform a session setup (async send)
+****************************************************************************/
+struct smbcli_request *smb_raw_sesssetup_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.workgroup, STR_TERMINATE);
+ break;
+
+ case RAW_SESSSETUP_SMB2:
+ return NULL;
+ }
+
+ if (!smbcli_request_send(req)) {
+ smbcli_request_destroy(req);
+ return NULL;
+ }
+
+ return req;
+}
+
+
+/****************************************************************************
+ Perform a session setup (async recv)
+****************************************************************************/
+NTSTATUS smb_raw_sesssetup_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->in.bufinfo, mem_ctx, &parms->old.out.os, p, -1, STR_TERMINATE);
+ p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->old.out.lanman, p, -1, STR_TERMINATE);
+ smbcli_req_pull_string(&req->in.bufinfo, 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->in.bufinfo, mem_ctx, &parms->nt1.out.os, p, -1, STR_TERMINATE);
+ p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->nt1.out.lanman, p, -1, STR_TERMINATE);
+ if (p < (req->in.data + req->in.data_size)) {
+ smbcli_req_pull_string(&req->in.bufinfo, 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->in.bufinfo, mem_ctx, p, len);
+ p += parms->spnego.out.secblob.length;
+ p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->spnego.out.os, p, -1, STR_TERMINATE);
+ p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->spnego.out.lanman, p, -1, STR_TERMINATE);
+ smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->spnego.out.workgroup, p, -1, STR_TERMINATE);
+ break;
+
+ case RAW_SESSSETUP_SMB2:
+ req->status = NT_STATUS_INTERNAL_ERROR;
+ break;
+ }
+
+failed:
+ return smbcli_request_destroy(req);
+}
+
+
+/*
+ Perform a session setup (sync interface)
+*/
+NTSTATUS smb_raw_sesssetup(struct smbcli_session *session,
+ TALLOC_CTX *mem_ctx, union smb_sesssetup *parms)
+{
+ struct smbcli_request *req = smb_raw_sesssetup_send(session, parms);
+ return smb_raw_sesssetup_recv(req, mem_ctx, parms);
+}
+
+
+/****************************************************************************
+ Send a ulogoff (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 ulogoff (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)
+*****************************************************************************/
+_PUBLIC_ NTSTATUS smb_raw_exit(struct smbcli_session *session)
+{
+ struct smbcli_request *req = smb_raw_exit_send(session);
+ return smbcli_request_simple_recv(req);
+}