Just hardcode workgroup to empty string, to avoid use of
[kai/samba.git] / source4 / libcli / raw / clitree.c
index c383eef768a084daa3cd2f9791ad4299bb0b4b98..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 = smbcli_request_setup(tree, cmd, wct, buflen); \
        if (!req) return NULL; \
 } while (0)
 
-
 /****************************************************************************
  Initialize the tree context
 ****************************************************************************/
-struct smbcli_tree *smbcli_tree_init(struct smbcli_session *session)
+_PUBLIC_ struct smbcli_tree *smbcli_tree_init(struct smbcli_session *session,
+                                    TALLOC_CTX *parent_ctx, bool primary)
 {
        struct smbcli_tree *tree;
 
-       tree = talloc_p(session, struct smbcli_tree);
+       tree = talloc_zero(parent_ctx, struct smbcli_tree);
        if (!tree) {
                return NULL;
        }
 
-       ZERO_STRUCTP(tree);
-       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 smbcli_tree_close(struct smbcli_tree *tree)
-{
-       if (!tree) return;
-       tree->reference_count--;
-       if (tree->reference_count <= 0) {
-               smbcli_session_close(tree->session);
-               talloc_free(tree);
-       }
+       return tree;
 }
 
-
 /****************************************************************************
  Send a tconX (async send)
 ****************************************************************************/
-struct smbcli_request *smb_tree_connect_send(struct smbcli_tree *tree, union smb_tcon *parms)
+struct smbcli_request *smb_raw_tcon_send(struct smbcli_tree *tree, 
+                                        union smb_tcon *parms)
 {
        struct smbcli_request *req = NULL;
 
@@ -85,6 +80,9 @@ struct smbcli_request *smb_tree_connect_send(struct smbcli_tree *tree, union smb
                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 (!smbcli_request_send(req)) {
@@ -98,9 +96,10 @@ struct smbcli_request *smb_tree_connect_send(struct smbcli_tree *tree, union smb
 /****************************************************************************
  Send a tconX (async recv)
 ****************************************************************************/
-NTSTATUS smb_tree_connect_recv(struct smbcli_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 (!smbcli_request_receive(req) ||
            smbcli_request_is_error(req)) {
@@ -111,12 +110,12 @@ NTSTATUS smb_tree_connect_recv(struct smbcli_request *req, TALLOC_CTX *mem_ctx,
        case RAW_TCON_TCON:
                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);
-               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));
                }
@@ -125,11 +124,15 @@ NTSTATUS smb_tree_connect_recv(struct smbcli_request *req, TALLOC_CTX *mem_ctx,
                p = req->in.data;
                if (!p) break;
 
-               p += smbcli_req_pull_string(req, mem_ctx, &parms->tconx.out.dev_type, 
-                                        p, -1, STR_ASCII | STR_TERMINATE);
-               p += smbcli_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:
@@ -139,17 +142,18 @@ failed:
 /****************************************************************************
  Send a tconX (sync interface)
 ****************************************************************************/
-NTSTATUS smb_tree_connect(struct smbcli_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 smbcli_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 smbcli_tree *tree)
+_PUBLIC_ NTSTATUS smb_tree_disconnect(struct smbcli_tree *tree)
 {
        struct smbcli_request *req;
 
@@ -157,147 +161,51 @@ NTSTATUS smb_tree_disconnect(struct smbcli_tree *tree)
        req = smbcli_request_setup(tree, SMBtdis, 0, 0);
 
        if (smbcli_request_send(req)) {
-               smbcli_request_receive(req);
+               (void) smbcli_request_receive(req);
        }
        return smbcli_request_destroy(req);
 }
 
 
 /*
-  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(struct smbcli_tree **ret_tree, 
-                                    const char *my_name, 
-                                    const char *dest_host, int port,
+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,
-                                    const char *user, const char *domain, 
-                                    const char *password)
+                                    struct cli_credentials *credentials,
+                                    struct resolve_context *resolve_ctx,
+                                    struct event_context *ev,
+                                    struct smbcli_options *options,
+                                    struct smbcli_session_options *session_options)
 {
-       struct smbcli_socket *sock;
-       struct smbcli_transport *transport;
-       struct smbcli_session *session;
-       struct smbcli_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;
-       char *in_path = NULL;
-
-       *ret_tree = NULL;
-
-       sock = smbcli_sock_init();
-       if (!sock) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       /* open a TCP socket to the server */
-       if (!smbcli_sock_connect_byname(sock, dest_host, port)) {
-               DEBUG(2,("Failed to establish socket connection - %s\n", strerror(errno)));
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-
-       transport = smbcli_transport_init(sock);
-       if (!transport) {
-               smbcli_sock_close(sock);
+       TALLOC_CTX *tmp_ctx = talloc_new(parent_ctx);
+       if (!tmp_ctx) {
                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)) {
-               smbcli_transport_close(transport);
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-
-
-       /* negotiate protocol options with the server */
-       status = smb_raw_negotiate(transport);
-       if (!NT_STATUS_IS_OK(status)) {
-               smbcli_transport_close(transport);
-               return status;
-       }
-
-       session = smbcli_session_init(transport);
-       if (!session) {
-               smbcli_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 = transport->negotiate.capabilities;
-       if (!user || !user[0]) {
-               setup.generic.in.password = NULL;
-               setup.generic.in.user = "";
-               setup.generic.in.domain = "";
-               setup.generic.in.capabilities &= ~CAP_EXTENDED_SECURITY;
-       } 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)) {
-               smbcli_session_close(session);
-               talloc_free(mem_ctx);
-               return status;
-       }
-
-       session->vuid = setup.generic.out.vuid;
-
-       tree = smbcli_tree_init(session);
-       if (!tree) {
-               smbcli_session_close(session);
-               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;
+       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);
-
-       SAFE_FREE(in_path);
-
-       if (!NT_STATUS_IS_OK(status)) {
-               smbcli_tree_close(tree);
-               talloc_free(mem_ctx);
-               return status;
-       }
-
-       tree->tid = tcon.tconx.out.cnum;
-       if (tcon.tconx.out.dev_type) {
-               tree->device = talloc_strdup(tree, 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, tcon.tconx.out.fs_type);
-       }
-
-       talloc_free(mem_ctx);
-
-       *ret_tree = tree;
-       return NT_STATUS_OK;
+       talloc_free(tmp_ctx);
+       return status;
 }