Just hardcode workgroup to empty string, to avoid use of
[kai/samba.git] / source4 / libcli / raw / clitree.c
index a088ae7023c83afb759053d79893efefedd33c41..ccfb28b84dba9b42fcc896388652443e23204d50 100644 (file)
@@ -1,12 +1,14 @@
 /* 
    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
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   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,
    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.
+   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 "libcli/smb_composite/smb_composite.h"
+#include "param/param.h"
 
 #define SETUP_REQUEST_TREE(cmd, wct, buflen) do { \
-       req = cli_request_setup(tree, cmd, wct, buflen); \
+       req = smbcli_request_setup(tree, cmd, wct, buflen); \
        if (!req) return NULL; \
 } while (0)
 
-
 /****************************************************************************
  Initialize the tree context
 ****************************************************************************/
-struct cli_tree *cli_tree_init(struct cli_session *session)
+_PUBLIC_ struct smbcli_tree *smbcli_tree_init(struct smbcli_session *session,
+                                    TALLOC_CTX *parent_ctx, bool primary)
 {
-       struct cli_tree *tree;
-       TALLOC_CTX *mem_ctx = talloc_init("cli_tree");
-       if (mem_ctx == NULL) {
-               return NULL;
-       }
+       struct smbcli_tree *tree;
 
-       tree = talloc_zero(mem_ctx, sizeof(*tree));
+       tree = talloc_zero(parent_ctx, struct smbcli_tree);
        if (!tree) {
-               talloc_destroy(mem_ctx);
                return NULL;
        }
 
-       tree->mem_ctx = mem_ctx;
-       tree->session = session;
-       tree->session->reference_count++;
+       if (primary) {
+               tree->session = talloc_steal(tree, session);
+       } else {
+               tree->session = talloc_reference(tree, session);
+       }
 
-       return tree;
-}
 
-/****************************************************************************
-reduce reference count on a tree and destroy if <= 0
-****************************************************************************/
-void cli_tree_close(struct cli_tree *tree)
-{
-       if (!tree) return;
-       tree->reference_count--;
-       if (tree->reference_count <= 0) {
-               cli_session_close(tree->session);
-               talloc_destroy(tree->mem_ctx);
-       }
+       return tree;
 }
 
-
 /****************************************************************************
  Send a tconX (async send)
 ****************************************************************************/
-struct cli_request *smb_tree_connect_send(struct cli_tree *tree, union smb_tcon *parms)
+struct smbcli_request *smb_raw_tcon_send(struct smbcli_tree *tree, 
+                                        union smb_tcon *parms)
 {
-       struct cli_request *req;
+       struct smbcli_request *req = NULL;
 
        switch (parms->tcon.level) {
        case RAW_TCON_TCON:
                SETUP_REQUEST_TREE(SMBtcon, 0, 0);
-               cli_req_append_ascii4(req, parms->tcon.in.service, STR_ASCII);
-               cli_req_append_ascii4(req, parms->tcon.in.password,STR_ASCII);
-               cli_req_append_ascii4(req, parms->tcon.in.dev,     STR_ASCII);
+               smbcli_req_append_ascii4(req, parms->tcon.in.service, STR_ASCII);
+               smbcli_req_append_ascii4(req, parms->tcon.in.password,STR_ASCII);
+               smbcli_req_append_ascii4(req, parms->tcon.in.dev,     STR_ASCII);
                break;
 
        case RAW_TCON_TCONX:
@@ -86,14 +76,17 @@ struct cli_request *smb_tree_connect_send(struct cli_tree *tree, union smb_tcon
                SSVAL(req->out.vwv, VWV(1), 0);
                SSVAL(req->out.vwv, VWV(2), parms->tconx.in.flags);
                SSVAL(req->out.vwv, VWV(3), parms->tconx.in.password.length);
-               cli_req_append_blob(req, &parms->tconx.in.password);
-               cli_req_append_string(req, parms->tconx.in.path,   STR_TERMINATE | STR_UPPER);
-               cli_req_append_string(req, parms->tconx.in.device, STR_TERMINATE | STR_ASCII);
+               smbcli_req_append_blob(req, &parms->tconx.in.password);
+               smbcli_req_append_string(req, parms->tconx.in.path,   STR_TERMINATE | STR_UPPER);
+               smbcli_req_append_string(req, parms->tconx.in.device, STR_TERMINATE | STR_ASCII);
                break;
+
+       case RAW_TCON_SMB2:
+               return NULL;
        }
 
-       if (!cli_request_send(req)) {
-               cli_request_destroy(req);
+       if (!smbcli_request_send(req)) {
+               smbcli_request_destroy(req);
                return NULL;
        }
 
@@ -103,26 +96,26 @@ struct cli_request *smb_tree_connect_send(struct cli_tree *tree, union smb_tcon
 /****************************************************************************
  Send a tconX (async recv)
 ****************************************************************************/
-NTSTATUS smb_tree_connect_recv(struct cli_request *req, TALLOC_CTX *mem_ctx, union smb_tcon *parms)
+NTSTATUS smb_raw_tcon_recv(struct smbcli_request *req, TALLOC_CTX *mem_ctx, 
+                          union smb_tcon *parms)
 {
-       char *p;
+       uint8_t *p;
 
-       if (!cli_request_receive(req) ||
-           cli_request_is_error(req)) {
+       if (!smbcli_request_receive(req) ||
+           smbcli_request_is_error(req)) {
                goto failed;
        }
 
        switch (parms->tcon.level) {
        case RAW_TCON_TCON:
-               CLI_CHECK_WCT(req, 2);
+               SMBCLI_CHECK_WCT(req, 2);
                parms->tcon.out.max_xmit = SVAL(req->in.vwv, VWV(0));
-               parms->tcon.out.cnum = SVAL(req->in.vwv, VWV(1));
+               parms->tcon.out.tid = SVAL(req->in.vwv, VWV(1));
                break;
 
        case RAW_TCON_TCONX:
                ZERO_STRUCT(parms->tconx.out);
-               CLI_CHECK_MIN_WCT(req, 0);  /* this depends on the protocol level */
-               parms->tconx.out.cnum = SVAL(req->in.hdr, HDR_TID);
+               parms->tconx.out.tid = SVAL(req->in.hdr, HDR_TID);
                if (req->in.wct >= 4) {
                        parms->tconx.out.options = SVAL(req->in.vwv, VWV(3));
                }
@@ -131,167 +124,88 @@ NTSTATUS smb_tree_connect_recv(struct cli_request *req, TALLOC_CTX *mem_ctx, uni
                p = req->in.data;
                if (!p) break;
 
-               p += cli_req_pull_string(req, mem_ctx, &parms->tconx.out.dev_type, 
-                                        p, -1, STR_ASCII | STR_TERMINATE);
-               p += cli_req_pull_string(req, mem_ctx, &parms->tconx.out.fs_type, 
+               p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->tconx.out.dev_type, 
+                                           p, -1, STR_ASCII | STR_TERMINATE);
+               p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->tconx.out.fs_type, 
                                         p, -1, STR_TERMINATE);
                break;
+
+       case RAW_TCON_SMB2:
+               req->status = NT_STATUS_INTERNAL_ERROR;
+               break;
        }
 
 failed:
-       return cli_request_destroy(req);
+       return smbcli_request_destroy(req);
 }
 
 /****************************************************************************
  Send a tconX (sync interface)
 ****************************************************************************/
-NTSTATUS smb_tree_connect(struct cli_tree *tree, TALLOC_CTX *mem_ctx, union smb_tcon *parms)
+_PUBLIC_ NTSTATUS smb_raw_tcon(struct smbcli_tree *tree, TALLOC_CTX *mem_ctx, 
+                     union smb_tcon *parms)
 {
-       struct cli_request *req = smb_tree_connect_send(tree, parms);
-       return smb_tree_connect_recv(req, mem_ctx, parms);
+       struct smbcli_request *req = smb_raw_tcon_send(tree, parms);
+       return smb_raw_tcon_recv(req, mem_ctx, parms);
 }
 
 
 /****************************************************************************
  Send a tree disconnect.
 ****************************************************************************/
-NTSTATUS smb_tree_disconnect(struct cli_tree *tree)
+_PUBLIC_ NTSTATUS smb_tree_disconnect(struct smbcli_tree *tree)
 {
-       struct cli_request *req;
+       struct smbcli_request *req;
 
        if (!tree) return NT_STATUS_OK;
-       req = cli_request_setup(tree, SMBtdis, 0, 0);
+       req = smbcli_request_setup(tree, SMBtdis, 0, 0);
 
-       if (cli_request_send(req)) {
-               cli_request_receive(req);
+       if (smbcli_request_send(req)) {
+               (void) smbcli_request_receive(req);
        }
-       return cli_request_destroy(req);
+       return smbcli_request_destroy(req);
 }
 
 
 /*
-  a convenient function to establish a cli_tree from scratch, using reasonable default
-  parameters
+  a convenient function to establish a smbcli_tree from scratch
 */
-NTSTATUS cli_tree_full_connection(struct cli_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)
+NTSTATUS smbcli_tree_full_connection(TALLOC_CTX *parent_ctx,
+                                    struct smbcli_tree **ret_tree, 
+                                    const char *dest_host, const char **dest_ports,
+                                    const char *service, const char *service_type,
+                                    struct cli_credentials *credentials,
+                                    struct resolve_context *resolve_ctx,
+                                    struct event_context *ev,
+                                    struct smbcli_options *options,
+                                    struct smbcli_session_options *session_options)
 {
-       struct cli_socket *sock;
-       struct cli_transport *transport;
-       struct cli_session *session;
-       struct cli_tree *tree;
+       struct smb_composite_connect io;
        NTSTATUS status;
-       struct nmb_name calling;
-       struct nmb_name called;
-       union smb_sesssetup setup;
-       union smb_tcon tcon;
-       TALLOC_CTX *mem_ctx;
-
-       *ret_tree = NULL;
-
-       sock = cli_sock_init();
-       if (!sock) {
+       TALLOC_CTX *tmp_ctx = talloc_new(parent_ctx);
+       if (!tmp_ctx) {
                return NT_STATUS_NO_MEMORY;
        }
 
-       /* open a TCP socket to the server */
-       if (!cli_sock_connect_byname(sock, dest_host, port)) {
-               DEBUG(2,("Failed to establish socket connection - %s\n", strerror(errno)));
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-
-       transport = cli_transport_init(sock);
-       if (!transport) {
-               cli_sock_close(sock);
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       /* send a NBT session request, if applicable */
-       make_nmb_name(&calling, my_name, 0x0);
-       make_nmb_name(&called,  dest_host, 0x20);
-
-       if (!cli_transport_connect(transport, &calling, &called)) {
-               cli_transport_close(transport);
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-
-
-       /* negotiate protocol options with the server */
-       status = smb_raw_negotiate(transport);
-       if (!NT_STATUS_IS_OK(status)) {
-               cli_transport_close(transport);
-               return status;
-       }
-
-       session = cli_session_init(transport);
-       if (!session) {
-               cli_transport_close(transport);
-               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 = CAP_UNICODE | CAP_STATUS32 | 
-               CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS | 
-               CAP_W2K_SMBS | CAP_LARGE_READX | CAP_LARGE_WRITEX;
-       setup.generic.in.password = password;
-       setup.generic.in.user = user;
-       setup.generic.in.domain = domain;
-
-       mem_ctx = talloc_init("tcon");
-       if (!mem_ctx) {
-               cli_tree_close(tree);
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       status = smb_raw_session_setup(session, mem_ctx, &setup);
-       if (!NT_STATUS_IS_OK(status)) {
-               cli_session_close(session);
-               talloc_destroy(mem_ctx);
-               return status;
-       }
-
-       session->vuid = setup.generic.out.vuid;
-
-       tree = cli_tree_init(session);
-       if (!tree) {
-               cli_session_close(session);
-               talloc_destroy(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(&tcon.tconx.in.path, "\\\\%s\\%s", dest_host, service);
-       tcon.tconx.in.device = service_type;
+       io.in.dest_host = dest_host;
+       io.in.dest_ports = dest_ports;
+       io.in.called_name = strupper_talloc(tmp_ctx, dest_host);
+       io.in.service = service;
+       io.in.service_type = service_type;
+       io.in.credentials = credentials;
+       io.in.fallback_to_anonymous = false;
+
+       /* This workgroup gets sent out by the SPNEGO session setup.
+        * I don't know of any servers that look at it, so we 
+        * hardcode it to "". */
+       io.in.workgroup = "";
+       io.in.options = *options;
+       io.in.session_options = *session_options;
        
-       status = smb_tree_connect(tree, mem_ctx, &tcon);
-
-       free(tcon.tconx.in.path);
-
-       if (!NT_STATUS_IS_OK(status)) {
-               cli_tree_close(tree);
-               talloc_destroy(mem_ctx);
-               return status;
-       }
-
-       tree->tid = tcon.tconx.out.cnum;
-       if (tcon.tconx.out.dev_type) {
-               tree->device = talloc_strdup(tree->mem_ctx, tcon.tconx.out.dev_type);
+       status = smb_composite_connect(&io, parent_ctx, resolve_ctx, ev);
+       if (NT_STATUS_IS_OK(status)) {
+               *ret_tree = io.out.tree;
        }
-       if (tcon.tconx.out.fs_type) {
-               tree->fs_type = talloc_strdup(tree->mem_ctx, tcon.tconx.out.fs_type);
-       }
-
-       talloc_destroy(mem_ctx);
-
-       *ret_tree = tree;
-       return NT_STATUS_OK;
+       talloc_free(tmp_ctx);
+       return status;
 }