r5929: Use cli_credentials for the SMB functions as well.
[samba.git] / source4 / libcli / raw / clitree.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    SMB client tree context management functions
5
6    Copyright (C) Andrew Tridgell 1994-2005
7    Copyright (C) James Myers 2003 <myersjj@samba.org>
8    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include "includes.h"
25 #include "libcli/raw/libcliraw.h"
26 #include "libcli/composite/composite.h"
27
28 #define SETUP_REQUEST_TREE(cmd, wct, buflen) do { \
29         req = smbcli_request_setup(tree, cmd, wct, buflen); \
30         if (!req) return NULL; \
31 } while (0)
32
33 /****************************************************************************
34  Initialize the tree context
35 ****************************************************************************/
36 struct smbcli_tree *smbcli_tree_init(struct smbcli_session *session,
37                                      TALLOC_CTX *parent_ctx, BOOL primary)
38 {
39         struct smbcli_tree *tree;
40
41         tree = talloc_zero(parent_ctx, struct smbcli_tree);
42         if (!tree) {
43                 return NULL;
44         }
45
46         if (primary) {
47                 tree->session = talloc_steal(tree, session);
48         } else {
49                 tree->session = talloc_reference(tree, session);
50         }
51
52
53         return tree;
54 }
55
56 /****************************************************************************
57  Send a tconX (async send)
58 ****************************************************************************/
59 struct smbcli_request *smb_tree_connect_send(struct smbcli_tree *tree, 
60                                              union smb_tcon *parms)
61 {
62         struct smbcli_request *req = NULL;
63
64         switch (parms->tcon.level) {
65         case RAW_TCON_TCON:
66                 SETUP_REQUEST_TREE(SMBtcon, 0, 0);
67                 smbcli_req_append_ascii4(req, parms->tcon.in.service, STR_ASCII);
68                 smbcli_req_append_ascii4(req, parms->tcon.in.password,STR_ASCII);
69                 smbcli_req_append_ascii4(req, parms->tcon.in.dev,     STR_ASCII);
70                 break;
71
72         case RAW_TCON_TCONX:
73                 SETUP_REQUEST_TREE(SMBtconX, 4, 0);
74                 SSVAL(req->out.vwv, VWV(0), 0xFF);
75                 SSVAL(req->out.vwv, VWV(1), 0);
76                 SSVAL(req->out.vwv, VWV(2), parms->tconx.in.flags);
77                 SSVAL(req->out.vwv, VWV(3), parms->tconx.in.password.length);
78                 smbcli_req_append_blob(req, &parms->tconx.in.password);
79                 smbcli_req_append_string(req, parms->tconx.in.path,   STR_TERMINATE | STR_UPPER);
80                 smbcli_req_append_string(req, parms->tconx.in.device, STR_TERMINATE | STR_ASCII);
81                 break;
82         }
83
84         if (!smbcli_request_send(req)) {
85                 smbcli_request_destroy(req);
86                 return NULL;
87         }
88
89         return req;
90 }
91
92 /****************************************************************************
93  Send a tconX (async recv)
94 ****************************************************************************/
95 NTSTATUS smb_tree_connect_recv(struct smbcli_request *req, TALLOC_CTX *mem_ctx, 
96                                union smb_tcon *parms)
97 {
98         uint8_t *p;
99
100         if (!smbcli_request_receive(req) ||
101             smbcli_request_is_error(req)) {
102                 goto failed;
103         }
104
105         switch (parms->tcon.level) {
106         case RAW_TCON_TCON:
107                 SMBCLI_CHECK_WCT(req, 2);
108                 parms->tcon.out.max_xmit = SVAL(req->in.vwv, VWV(0));
109                 parms->tcon.out.tid = SVAL(req->in.vwv, VWV(1));
110                 break;
111
112         case RAW_TCON_TCONX:
113                 ZERO_STRUCT(parms->tconx.out);
114                 parms->tconx.out.tid = SVAL(req->in.hdr, HDR_TID);
115                 if (req->in.wct >= 4) {
116                         parms->tconx.out.options = SVAL(req->in.vwv, VWV(3));
117                 }
118
119                 /* output is actual service name */
120                 p = req->in.data;
121                 if (!p) break;
122
123                 p += smbcli_req_pull_string(req, mem_ctx, &parms->tconx.out.dev_type, 
124                                          p, -1, STR_ASCII | STR_TERMINATE);
125                 p += smbcli_req_pull_string(req, mem_ctx, &parms->tconx.out.fs_type, 
126                                          p, -1, STR_TERMINATE);
127                 break;
128         }
129
130 failed:
131         return smbcli_request_destroy(req);
132 }
133
134 /****************************************************************************
135  Send a tconX (sync interface)
136 ****************************************************************************/
137 NTSTATUS smb_tree_connect(struct smbcli_tree *tree, TALLOC_CTX *mem_ctx, 
138                           union smb_tcon *parms)
139 {
140         struct smbcli_request *req = smb_tree_connect_send(tree, parms);
141         return smb_tree_connect_recv(req, mem_ctx, parms);
142 }
143
144
145 /****************************************************************************
146  Send a tree disconnect.
147 ****************************************************************************/
148 NTSTATUS smb_tree_disconnect(struct smbcli_tree *tree)
149 {
150         struct smbcli_request *req;
151
152         if (!tree) return NT_STATUS_OK;
153         req = smbcli_request_setup(tree, SMBtdis, 0, 0);
154
155         if (smbcli_request_send(req)) {
156                 smbcli_request_receive(req);
157         }
158         return smbcli_request_destroy(req);
159 }
160
161
162 /*
163   a convenient function to establish a smbcli_tree from scratch
164 */
165 NTSTATUS smbcli_tree_full_connection(TALLOC_CTX *parent_ctx,
166                                      struct smbcli_tree **ret_tree, 
167                                      const char *my_name, 
168                                      const char *dest_host, int port,
169                                      const char *service, const char *service_type,
170                                          struct cli_credentials *credentials)
171 {
172         struct smb_composite_connect io;
173         NTSTATUS status;
174
175         io.in.dest_host = dest_host;
176         io.in.port = port;
177         io.in.called_name = strupper_talloc(parent_ctx, dest_host);
178         io.in.calling_name = strupper_talloc(parent_ctx, my_name);
179         io.in.service = service;
180         io.in.service_type = service_type;
181         io.in.domain = cli_credentials_get_domain(credentials);
182         io.in.user = cli_credentials_get_username(credentials);
183         if (!cli_credentials_is_anonymous(credentials)) {
184                 io.in.password = cli_credentials_get_password(credentials);
185         } else {
186                 io.in.password = NULL;
187         }
188         
189         status = smb_composite_connect(&io, parent_ctx);
190         if (NT_STATUS_IS_OK(status)) {
191                 *ret_tree = io.out.tree;
192         }
193
194         return status;
195 }