summaryrefslogtreecommitdiff
path: root/source4/libcli/raw
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2005-01-16 11:15:08 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:08:53 -0500
commit7cbc768376ed0a839afca64aeea99cd53d0fbc6f (patch)
tree116b18a6fc59ec306275f32c136201f83708e5fc /source4/libcli/raw
parent6eabc2a711446819e0694bd56eb71ea7f101ae66 (diff)
downloadsamba-7cbc768376ed0a839afca64aeea99cd53d0fbc6f.tar.gz
samba-7cbc768376ed0a839afca64aeea99cd53d0fbc6f.tar.bz2
samba-7cbc768376ed0a839afca64aeea99cd53d0fbc6f.zip
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)
Diffstat (limited to 'source4/libcli/raw')
-rw-r--r--source4/libcli/raw/clisession.c358
-rw-r--r--source4/libcli/raw/clisocket.c2
-rw-r--r--source4/libcli/raw/clitransport.c3
-rw-r--r--source4/libcli/raw/clitree.c147
4 files changed, 14 insertions, 496 deletions
diff --git a/source4/libcli/raw/clisession.c b/source4/libcli/raw/clisession.c
index 46236217ea..ed50601c25 100644
--- a/source4/libcli/raw/clisession.c
+++ b/source4/libcli/raw/clisession.c
@@ -1,7 +1,8 @@
/*
Unix SMB/CIFS implementation.
SMB client session context management functions
- Copyright (C) Andrew Tridgell 1994-1998
+
+ 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
@@ -76,11 +77,7 @@ struct smbcli_request *smb_raw_session_setup_send(struct smbcli_session *session
{
struct smbcli_request *req = NULL;
- switch (parms->generic.level) {
- case RAW_SESSSETUP_GENERIC:
- /* handled elsewhere */
- return NULL;
-
+ switch (parms->old.level) {
case RAW_SESSSETUP_OLD:
SETUP_REQUEST_SESSION(SMBsesssetupX, 10, 0);
SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
@@ -164,11 +161,7 @@ NTSTATUS smb_raw_session_setup_recv(struct smbcli_request *req,
return smbcli_request_destroy(req);
}
- switch (parms->generic.level) {
- case RAW_SESSSETUP_GENERIC:
- /* handled elsewhere */
- return NT_STATUS_INVALID_LEVEL;
-
+ switch (parms->old.level) {
case RAW_SESSSETUP_OLD:
SMBCLI_CHECK_WCT(req, 3);
ZERO_STRUCT(parms->old.out);
@@ -220,353 +213,14 @@ failed:
return smbcli_request_destroy(req);
}
-/*
- form an encrypted lanman password from a plaintext password
- and the server supplied challenge
-*/
-static DATA_BLOB lanman_blob(const char *pass, DATA_BLOB challenge)
-{
- DATA_BLOB blob = data_blob(NULL, 24);
- SMBencrypt(pass, challenge.data, blob.data);
- return blob;
-}
-
-/*
- form an encrypted NT password from a plaintext password
- and the server supplied challenge
-*/
-static DATA_BLOB nt_blob(const char *pass, DATA_BLOB challenge)
-{
- DATA_BLOB blob = data_blob(NULL, 24);
- SMBNTencrypt(pass, challenge.data, blob.data);
- return blob;
-}
-
-/*
- store the user session key for a transport
-*/
-void smbcli_session_set_user_session_key(struct smbcli_session *session,
- const DATA_BLOB *session_key)
-{
- session->user_session_key = data_blob_talloc(session,
- session_key->data,
- session_key->length);
-}
/*
- setup signing for a NT1 style session setup
-*/
-void smb_session_use_nt1_session_keys(struct smbcli_session *session,
- const char *password, const DATA_BLOB *nt_response)
-{
- struct smbcli_transport *transport = session->transport;
- uint8_t nt_hash[16];
- DATA_BLOB session_key = data_blob(NULL, 16);
-
- E_md4hash(password, nt_hash);
- SMBsesskeygen_ntv1(nt_hash, session_key.data);
-
- smbcli_transport_simple_set_signing(transport, session_key, *nt_response);
-
- smbcli_session_set_user_session_key(session, &session_key);
- data_blob_free(&session_key);
-}
-
-/****************************************************************************
- Perform a session setup (sync interface) using generic interface and the old
- style sesssetup call
-****************************************************************************/
-static NTSTATUS smb_raw_session_setup_generic_old(struct smbcli_session *session,
- TALLOC_CTX *mem_ctx,
- union smb_sesssetup *parms)
-{
- NTSTATUS status;
- union smb_sesssetup s2;
-
- /* use the old interface */
- s2.generic.level = RAW_SESSSETUP_OLD;
- s2.old.in.bufsize = session->transport->options.max_xmit;
- s2.old.in.mpx_max = session->transport->options.max_mux;
- s2.old.in.vc_num = 1;
- s2.old.in.sesskey = parms->generic.in.sesskey;
- s2.old.in.domain = parms->generic.in.domain;
- s2.old.in.user = parms->generic.in.user;
- s2.old.in.os = "Unix";
- s2.old.in.lanman = "Samba";
-
- if (!parms->generic.in.password) {
- s2.old.in.password = data_blob(NULL, 0);
- } else if (session->transport->negotiate.sec_mode &
- NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) {
- s2.old.in.password = lanman_blob(parms->generic.in.password,
- session->transport->negotiate.secblob);
- } else {
- s2.old.in.password = data_blob(parms->generic.in.password,
- strlen(parms->generic.in.password));
- }
-
- status = smb_raw_session_setup(session, mem_ctx, &s2);
-
- data_blob_free(&s2.old.in.password);
-
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- parms->generic.out.vuid = s2.old.out.vuid;
- parms->generic.out.os = s2.old.out.os;
- parms->generic.out.lanman = s2.old.out.lanman;
- parms->generic.out.domain = s2.old.out.domain;
-
- return NT_STATUS_OK;
-}
-
-/****************************************************************************
- Perform a session setup (sync interface) using generic interface and the NT1
- style sesssetup call
-****************************************************************************/
-static NTSTATUS smb_raw_session_setup_generic_nt1(struct smbcli_session *session,
- TALLOC_CTX *mem_ctx,
- union smb_sesssetup *parms)
-{
- NTSTATUS status;
- union smb_sesssetup s2;
-
- s2.generic.level = RAW_SESSSETUP_NT1;
- s2.nt1.in.bufsize = session->transport->options.max_xmit;
- s2.nt1.in.mpx_max = session->transport->options.max_mux;
- s2.nt1.in.vc_num = 1;
- s2.nt1.in.sesskey = parms->generic.in.sesskey;
- s2.nt1.in.capabilities = parms->generic.in.capabilities;
- s2.nt1.in.domain = parms->generic.in.domain;
- s2.nt1.in.user = parms->generic.in.user;
- s2.nt1.in.os = "Unix";
- s2.nt1.in.lanman = "Samba";
-
- if (!parms->generic.in.password) {
- s2.nt1.in.password1 = data_blob(NULL, 0);
- s2.nt1.in.password2 = data_blob(NULL, 0);
- } else if (session->transport->negotiate.sec_mode &
- NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) {
- s2.nt1.in.password1 = lanman_blob(parms->generic.in.password,
- session->transport->negotiate.secblob);
- s2.nt1.in.password2 = nt_blob(parms->generic.in.password,
- session->transport->negotiate.secblob);
- smb_session_use_nt1_session_keys(session, parms->generic.in.password, &s2.nt1.in.password2);
-
- } else {
- s2.nt1.in.password1 = data_blob(parms->generic.in.password,
- strlen(parms->generic.in.password));
- s2.nt1.in.password2 = data_blob(NULL, 0);
- }
-
- status = smb_raw_session_setup(session, mem_ctx, &s2);
-
- data_blob_free(&s2.nt1.in.password1);
- data_blob_free(&s2.nt1.in.password2);
-
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- parms->generic.out.vuid = s2.nt1.out.vuid;
- parms->generic.out.os = s2.nt1.out.os;
- parms->generic.out.lanman = s2.nt1.out.lanman;
- parms->generic.out.domain = s2.nt1.out.domain;
-
- return NT_STATUS_OK;
-}
-
-/****************************************************************************
- Perform a session setup (sync interface) using generic interface and the SPNEGO
- style sesssetup call
-****************************************************************************/
-static NTSTATUS smb_raw_session_setup_generic_spnego(struct smbcli_session *session,
- TALLOC_CTX *mem_ctx,
- union smb_sesssetup *parms)
-{
- NTSTATUS status;
- NTSTATUS session_key_err = NT_STATUS_NO_USER_SESSION_KEY;
- union smb_sesssetup s2;
- DATA_BLOB session_key = data_blob(NULL, 0);
- DATA_BLOB null_data_blob = data_blob(NULL, 0);
- const char *chosen_oid = NULL;
-
- s2.generic.level = RAW_SESSSETUP_SPNEGO;
- s2.spnego.in.bufsize = session->transport->options.max_xmit;
- s2.spnego.in.mpx_max = session->transport->options.max_mux;
- s2.spnego.in.vc_num = 1;
- s2.spnego.in.sesskey = parms->generic.in.sesskey;
- s2.spnego.in.capabilities = parms->generic.in.capabilities;
- s2.spnego.in.domain = parms->generic.in.domain;
- s2.spnego.in.os = "Unix";
- s2.spnego.in.lanman = "Samba";
- s2.spnego.out.vuid = session->vuid;
-
- smbcli_temp_set_signing(session->transport);
-
- status = gensec_client_start(session, &session->gensec);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1, ("Failed to start GENSEC client mode: %s\n", nt_errstr(status)));
- return status;
- }
-
- gensec_want_feature(session->gensec, GENSEC_FEATURE_SESSION_KEY);
-
- status = gensec_set_domain(session->gensec, parms->generic.in.domain);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1, ("Failed to start set GENSEC client domain to %s: %s\n",
- parms->generic.in.domain, nt_errstr(status)));
- goto done;
- }
-
- status = gensec_set_username(session->gensec, parms->generic.in.user);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1, ("Failed to start set GENSEC client username to %s: %s\n",
- parms->generic.in.user, nt_errstr(status)));
- goto done;
- }
-
- status = gensec_set_password(session->gensec, parms->generic.in.password);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1, ("Failed to start set GENSEC client password: %s\n",
- nt_errstr(status)));
- goto done;
- }
-
- status = gensec_set_target_hostname(session->gensec, session->transport->socket->hostname);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1, ("Failed to start set GENSEC target hostname: %s\n",
- nt_errstr(status)));
- goto done;
- }
-
- if (session->transport->negotiate.secblob.length) {
- chosen_oid = GENSEC_OID_SPNEGO;
- } else {
- /* without a sec blob, means raw NTLMSSP */
- chosen_oid = GENSEC_OID_NTLMSSP;
- }
-
- status = gensec_start_mech_by_oid(session->gensec, chosen_oid);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1, ("Failed to start set GENSEC client SPNEGO mechanism %s: %s\n",
- gensec_get_name_by_oid(chosen_oid), nt_errstr(status)));
- goto done;
- }
-
- status = gensec_update(session->gensec, mem_ctx,
- session->transport->negotiate.secblob,
- &s2.spnego.in.secblob);
-
- while(1) {
- if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) {
- break;
- }
-
- if (!NT_STATUS_IS_OK(session_key_err)) {
- session_key_err = gensec_session_key(session->gensec, &session_key);
- }
- if (NT_STATUS_IS_OK(session_key_err)) {
- smbcli_transport_simple_set_signing(session->transport, session_key, null_data_blob);
- }
-
- if (NT_STATUS_IS_OK(status) && s2.spnego.in.secblob.length == 0) {
- break;
- }
-
- session->vuid = s2.spnego.out.vuid;
- status = smb_raw_session_setup(session, mem_ctx, &s2);
- session->vuid = UID_FIELD_INVALID;
- if (!NT_STATUS_IS_OK(status) &&
- !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
- break;
- }
-
- status = gensec_update(session->gensec, mem_ctx,
- s2.spnego.out.secblob,
- &s2.spnego.in.secblob);
-
- }
-
-done:
- if (NT_STATUS_IS_OK(status)) {
- if (!NT_STATUS_IS_OK(session_key_err)) {
- DEBUG(1, ("Failed to get user session key: %s\n", nt_errstr(session_key_err)));
- return session_key_err;
- }
-
- smbcli_session_set_user_session_key(session, &session_key);
-
- parms->generic.out.vuid = s2.spnego.out.vuid;
- parms->generic.out.os = s2.spnego.out.os;
- parms->generic.out.lanman = s2.spnego.out.lanman;
- parms->generic.out.domain = s2.spnego.out.domain;
- } else {
- talloc_free(session->gensec);
- session->gensec = NULL;
- DEBUG(1, ("Failed to login with %s: %s\n", gensec_get_name_by_oid(chosen_oid), nt_errstr(status)));
- return status;
- }
-
- return status;
-}
-
-/****************************************************************************
- Perform a session setup (sync interface) using generic interface
-****************************************************************************/
-static NTSTATUS smb_raw_session_setup_generic(struct smbcli_session *session,
- TALLOC_CTX *mem_ctx,
- union smb_sesssetup *parms)
-{
- if (session->transport->negotiate.protocol < PROTOCOL_LANMAN1) {
- /* no session setup at all in earliest protocols */
- ZERO_STRUCT(parms->generic.out);
- return NT_STATUS_OK;
- }
-
- /* see if we need to use the original session setup interface */
- if (session->transport->negotiate.protocol < PROTOCOL_NT1) {
- return smb_raw_session_setup_generic_old(session, mem_ctx, parms);
- }
-
- /* see if we should use the NT1 interface */
- if (!session->transport->options.use_spnego ||
- !(parms->generic.in.capabilities & CAP_EXTENDED_SECURITY)) {
- return smb_raw_session_setup_generic_nt1(session, mem_ctx, parms);
- }
-
- /* default to using SPNEGO/NTLMSSP */
- return smb_raw_session_setup_generic_spnego(session, mem_ctx, parms);
-}
-
-
-/****************************************************************************
Perform a session setup (sync interface)
-this interface allows for RAW_SESSSETUP_GENERIC to auto-select session
-setup variant based on negotiated protocol options
-****************************************************************************/
+*/
NTSTATUS smb_raw_session_setup(struct smbcli_session *session, TALLOC_CTX *mem_ctx,
union smb_sesssetup *parms)
{
- struct smbcli_request *req;
-
- if (parms->generic.level == RAW_SESSSETUP_GENERIC) {
- NTSTATUS ret = smb_raw_session_setup_generic(session, mem_ctx, parms);
-
- if (NT_STATUS_IS_OK(ret)
- && parms->generic.in.user
- && *parms->generic.in.user) {
- if (!session->transport->negotiate.sign_info.doing_signing
- && session->transport->negotiate.sign_info.mandatory_signing) {
- DEBUG(0, ("SMB signing required, but server does not support it\n"));
- return NT_STATUS_ACCESS_DENIED;
- }
- }
- return ret;
- }
-
- req = smb_raw_session_setup_send(session, parms);
+ struct smbcli_request *req = smb_raw_session_setup_send(session, parms);
return smb_raw_session_setup_recv(req, mem_ctx, parms);
}
diff --git a/source4/libcli/raw/clisocket.c b/source4/libcli/raw/clisocket.c
index 851cf67caa..ad1c6a13b8 100644
--- a/source4/libcli/raw/clisocket.c
+++ b/source4/libcli/raw/clisocket.c
@@ -1,5 +1,6 @@
/*
Unix SMB/CIFS implementation.
+
SMB client socket context management functions
Copyright (C) Andrew Tridgell 1994-2005
@@ -72,6 +73,7 @@ static void smbcli_sock_connect_handler(struct event_context *ev, struct fd_even
c->status = socket_connect_complete(conn->sock->sock, 0);
if (NT_STATUS_IS_OK(c->status)) {
socket_set_option(conn->sock->sock, lp_socket_options(), NULL);
+ conn->sock->hostname = talloc_strdup(conn->sock, conn->dest_host);
c->state = SMBCLI_REQUEST_DONE;
if (c->async.fn) {
c->async.fn(c);
diff --git a/source4/libcli/raw/clitransport.c b/source4/libcli/raw/clitransport.c
index 14c0779968..55a7e25f72 100644
--- a/source4/libcli/raw/clitransport.c
+++ b/source4/libcli/raw/clitransport.c
@@ -1,7 +1,8 @@
/*
Unix SMB/CIFS implementation.
SMB client transport context management functions
- Copyright (C) Andrew Tridgell 1994-2003
+
+ 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
diff --git a/source4/libcli/raw/clitree.c b/source4/libcli/raw/clitree.c
index 7339ca07f1..c6b3fa5ad9 100644
--- a/source4/libcli/raw/clitree.c
+++ b/source4/libcli/raw/clitree.c
@@ -1,7 +1,9 @@
/*
Unix SMB/CIFS implementation.
+
SMB client tree context management functions
- Copyright (C) Andrew Tridgell 1994-1998
+
+ 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
@@ -152,8 +154,7 @@ NTSTATUS smb_tree_disconnect(struct smbcli_tree *tree)
/*
- a convenient function to establish a smbcli_tree from scratch, using reasonable default
- parameters
+ a convenient function to establish a smbcli_tree from scratch
*/
NTSTATUS smbcli_tree_full_connection(TALLOC_CTX *parent_ctx,
struct smbcli_tree **ret_tree,
@@ -163,146 +164,6 @@ NTSTATUS smbcli_tree_full_connection(TALLOC_CTX *parent_ctx,
const char *user, const char *domain,
const char *password)
{
- struct smbcli_socket *sock;
- struct smbcli_transport *transport;
- struct smbcli_session *session;
- struct smbcli_tree *tree;
- NTSTATUS status;
- struct nmb_name calling;
- struct nmb_name called;
- union smb_sesssetup setup;
- union smb_tcon tcon;
- TALLOC_CTX *mem_ctx;
- char *in_path = NULL;
-
- *ret_tree = NULL;
-
- sock = smbcli_sock_init(parent_ctx);
- if (!sock) {
- return NT_STATUS_NO_MEMORY;
- }
-
- /* open a TCP socket to the server */
- if (!smbcli_sock_connect_byname(sock, dest_host, port)) {
- talloc_free(sock);
- DEBUG(2,("Failed to establish socket connection - %s\n", strerror(errno)));
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- transport = smbcli_transport_init(sock);
- talloc_free(sock);
- if (!transport) {
- return NT_STATUS_NO_MEMORY;
- }
-
- /* send a NBT session request, if applicable */
- make_nmb_name(&calling, my_name, 0x0);
- choose_called_name(&called, dest_host, 0x20);
-
- if (!smbcli_transport_connect(transport, &calling, &called)) {
- talloc_free(transport);
- return NT_STATUS_UNSUCCESSFUL;
- }
-
-
- /* negotiate protocol options with the server */
- status = smb_raw_negotiate(transport, lp_maxprotocol());
- if (!NT_STATUS_IS_OK(status)) {
- talloc_free(transport);
- return status;
- }
-
- session = smbcli_session_init(transport);
- talloc_free(transport);
- if (!session) {
- return NT_STATUS_NO_MEMORY;
- }
-
- /* prepare a session setup to establish a security context */
- setup.generic.level = RAW_SESSSETUP_GENERIC;
- setup.generic.in.sesskey = transport->negotiate.sesskey;
- setup.generic.in.capabilities = transport->negotiate.capabilities;
- if (!user || !user[0]) {
- setup.generic.in.password = NULL;
- setup.generic.in.user = "";
- setup.generic.in.domain = "";
- } else {
- setup.generic.in.password = password;
- setup.generic.in.user = user;
- setup.generic.in.domain = domain;
- }
-
- mem_ctx = talloc_init("tcon");
- if (!mem_ctx) {
- return NT_STATUS_NO_MEMORY;
- }
-
- status = smb_raw_session_setup(session, mem_ctx, &setup);
- if (!NT_STATUS_IS_OK(status)) {
- talloc_free(session);
- talloc_free(mem_ctx);
- return status;
- }
-
- session->vuid = setup.generic.out.vuid;
-
- tree = smbcli_tree_init(session);
- talloc_free(session);
- if (!tree) {
- talloc_free(mem_ctx);
- return NT_STATUS_NO_MEMORY;
- }
-
- /* connect to a share using a tree connect */
- tcon.generic.level = RAW_TCON_TCONX;
- tcon.tconx.in.flags = 0;
- tcon.tconx.in.password = data_blob(NULL, 0);
- asprintf(&in_path, "\\\\%s\\%s", dest_host, service);
- tcon.tconx.in.path = in_path;
- if (!service_type) {
- if (strequal(service, "IPC$"))
- service_type = "IPC";
- else
- service_type = "?????";
- }
- tcon.tconx.in.device = service_type;
-
- status = smb_tree_connect(tree, mem_ctx, &tcon);
-
- SAFE_FREE(in_path);
-
- if (!NT_STATUS_IS_OK(status)) {
- talloc_free(tree);
- talloc_free(mem_ctx);
- return status;
- }
-
- tree->tid = tcon.tconx.out.tid;
- if (tcon.tconx.out.dev_type) {
- tree->device = talloc_strdup(tree, tcon.tconx.out.dev_type);
- }
- if (tcon.tconx.out.fs_type) {
- tree->fs_type = talloc_strdup(tree, tcon.tconx.out.fs_type);
- }
-
- talloc_free(mem_ctx);
-
- *ret_tree = tree;
- return NT_STATUS_OK;
-}
-
-
-/*
- a convenient function to establish a smbcli_tree from scratch
-*/
-NTSTATUS async_smbcli_tree_full_connection(TALLOC_CTX *parent_ctx,
- struct smbcli_tree **ret_tree,
- const char *my_name,
- const char *dest_host, int port,
- const char *service, const char *service_type,
- const char *user, const char *domain,
- const char *password)
-{
struct smb_composite_connect io;
NTSTATUS status;