Line data Source code
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 3 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, see <http://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include "includes.h"
24 : #include "libcli/raw/libcliraw.h"
25 : #include "libcli/raw/raw_proto.h"
26 : #include "libcli/smb_composite/smb_composite.h"
27 : #include "../libcli/smb/smbXcli_base.h"
28 :
29 : #define SETUP_REQUEST_TREE(cmd, wct, buflen) do { \
30 : req = smbcli_request_setup(tree, cmd, wct, buflen); \
31 : if (!req) return NULL; \
32 : } while (0)
33 :
34 : /****************************************************************************
35 : Initialize the tree context
36 : ****************************************************************************/
37 923 : _PUBLIC_ struct smbcli_tree *smbcli_tree_init(struct smbcli_session *session,
38 : TALLOC_CTX *parent_ctx, bool primary)
39 : {
40 : struct smbcli_tree *tree;
41 :
42 923 : tree = talloc_zero(parent_ctx, struct smbcli_tree);
43 923 : if (!tree) {
44 0 : return NULL;
45 : }
46 :
47 923 : if (primary) {
48 916 : tree->session = talloc_steal(tree, session);
49 : } else {
50 7 : tree->session = talloc_reference(tree, session);
51 : }
52 :
53 923 : tree->smbXcli = smbXcli_tcon_create(tree);
54 923 : if (tree->smbXcli == NULL) {
55 0 : talloc_free(tree);
56 0 : return NULL;
57 : }
58 :
59 923 : return tree;
60 : }
61 :
62 : /****************************************************************************
63 : Send a tconX (async send)
64 : ****************************************************************************/
65 919 : struct smbcli_request *smb_raw_tcon_send(struct smbcli_tree *tree,
66 : union smb_tcon *parms)
67 : {
68 919 : struct smbcli_request *req = NULL;
69 :
70 919 : switch (parms->tcon.level) {
71 0 : case RAW_TCON_TCON:
72 0 : SETUP_REQUEST_TREE(SMBtcon, 0, 0);
73 0 : smbcli_req_append_ascii4(req, parms->tcon.in.service, STR_ASCII);
74 0 : smbcli_req_append_ascii4(req, parms->tcon.in.password,STR_ASCII);
75 0 : smbcli_req_append_ascii4(req, parms->tcon.in.dev, STR_ASCII);
76 0 : break;
77 :
78 919 : case RAW_TCON_TCONX:
79 919 : SETUP_REQUEST_TREE(SMBtconX, 4, 0);
80 919 : SSVAL(req->out.vwv, VWV(0), 0xFF);
81 919 : SSVAL(req->out.vwv, VWV(1), 0);
82 919 : SSVAL(req->out.vwv, VWV(2), parms->tconx.in.flags);
83 919 : SSVAL(req->out.vwv, VWV(3), parms->tconx.in.password.length);
84 919 : smbcli_req_append_blob(req, &parms->tconx.in.password);
85 919 : smbcli_req_append_string(req, parms->tconx.in.path, STR_TERMINATE | STR_UPPER);
86 919 : smbcli_req_append_string(req, parms->tconx.in.device, STR_TERMINATE | STR_ASCII);
87 919 : break;
88 :
89 0 : case RAW_TCON_SMB2:
90 0 : return NULL;
91 : }
92 :
93 919 : if (!smbcli_request_send(req)) {
94 0 : smbcli_request_destroy(req);
95 0 : return NULL;
96 : }
97 :
98 919 : return req;
99 : }
100 :
101 : /****************************************************************************
102 : Send a tconX (async recv)
103 : ****************************************************************************/
104 919 : NTSTATUS smb_raw_tcon_recv(struct smbcli_request *req, TALLOC_CTX *mem_ctx,
105 : union smb_tcon *parms)
106 : {
107 : uint8_t *p;
108 :
109 1838 : if (!smbcli_request_receive(req) ||
110 919 : smbcli_request_is_error(req)) {
111 0 : goto failed;
112 : }
113 :
114 906 : switch (parms->tcon.level) {
115 0 : case RAW_TCON_TCON:
116 0 : SMBCLI_CHECK_WCT(req, 2);
117 0 : parms->tcon.out.max_xmit = SVAL(req->in.vwv, VWV(0));
118 0 : parms->tcon.out.tid = SVAL(req->in.vwv, VWV(1));
119 43 : break;
120 :
121 906 : case RAW_TCON_TCONX:
122 906 : ZERO_STRUCT(parms->tconx.out);
123 906 : parms->tconx.out.tid = SVAL(req->in.hdr, HDR_TID);
124 906 : if (req->in.wct >= 3) {
125 906 : parms->tconx.out.options = SVAL(req->in.vwv, VWV(2));
126 : }
127 906 : if (req->in.wct >= 7) {
128 18 : parms->tconx.out.max_access = IVAL(req->in.vwv, VWV(3));
129 18 : parms->tconx.out.guest_max_access = IVAL(req->in.vwv, VWV(5));
130 : }
131 :
132 : /* output is actual service name */
133 906 : p = req->in.data;
134 906 : if (!p) break;
135 :
136 906 : p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->tconx.out.dev_type,
137 : p, -1, STR_ASCII | STR_TERMINATE);
138 906 : smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->tconx.out.fs_type,
139 : p, -1, STR_TERMINATE);
140 906 : break;
141 :
142 0 : case RAW_TCON_SMB2:
143 0 : req->status = NT_STATUS_INTERNAL_ERROR;
144 0 : break;
145 : }
146 :
147 932 : failed:
148 919 : return smbcli_request_destroy(req);
149 : }
150 :
151 : /****************************************************************************
152 : Send a tconX (sync interface)
153 : ****************************************************************************/
154 29 : _PUBLIC_ NTSTATUS smb_raw_tcon(struct smbcli_tree *tree, TALLOC_CTX *mem_ctx,
155 : union smb_tcon *parms)
156 : {
157 29 : struct smbcli_request *req = smb_raw_tcon_send(tree, parms);
158 29 : return smb_raw_tcon_recv(req, mem_ctx, parms);
159 : }
160 :
161 :
162 : /****************************************************************************
163 : Send a tree disconnect.
164 : ****************************************************************************/
165 44 : _PUBLIC_ NTSTATUS smb_tree_disconnect(struct smbcli_tree *tree)
166 : {
167 : struct smbcli_request *req;
168 :
169 44 : if (!tree) return NT_STATUS_OK;
170 40 : req = smbcli_request_setup(tree, SMBtdis, 0, 0);
171 40 : if (req == NULL) {
172 0 : return NT_STATUS_NO_MEMORY;
173 : }
174 :
175 40 : if (smbcli_request_send(req)) {
176 40 : (void) smbcli_request_receive(req);
177 : }
178 40 : return smbcli_request_destroy(req);
179 : }
180 :
181 :
182 : /*
183 : a convenient function to establish a smbcli_tree from scratch
184 : */
185 756 : NTSTATUS smbcli_tree_full_connection(TALLOC_CTX *parent_ctx,
186 : struct smbcli_tree **ret_tree,
187 : const char *dest_host, const char **dest_ports,
188 : const char *service, const char *service_type,
189 : const char *socket_options,
190 : struct cli_credentials *credentials,
191 : struct resolve_context *resolve_ctx,
192 : struct tevent_context *ev,
193 : struct smbcli_options *options,
194 : struct smbcli_session_options *session_options,
195 : struct gensec_settings *gensec_settings)
196 : {
197 : struct smb_composite_connect io;
198 : NTSTATUS status;
199 756 : TALLOC_CTX *tmp_ctx = talloc_new(parent_ctx);
200 756 : if (!tmp_ctx) {
201 0 : return NT_STATUS_NO_MEMORY;
202 : }
203 :
204 756 : io.in.dest_host = dest_host;
205 756 : io.in.dest_ports = dest_ports;
206 756 : io.in.socket_options = socket_options;
207 756 : io.in.called_name = strupper_talloc(tmp_ctx, dest_host);
208 756 : io.in.service = service;
209 756 : io.in.service_type = service_type;
210 756 : io.in.existing_conn = NULL;
211 756 : io.in.credentials = credentials;
212 756 : io.in.gensec_settings = gensec_settings;
213 756 : io.in.fallback_to_anonymous = false;
214 :
215 : /* This workgroup gets sent out by the SPNEGO session setup.
216 : * I don't know of any servers that look at it, so we
217 : * hardcode it to "". */
218 756 : io.in.workgroup = "";
219 756 : io.in.options = *options;
220 756 : io.in.session_options = *session_options;
221 :
222 756 : status = smb_composite_connect(&io, parent_ctx, resolve_ctx, ev);
223 748 : if (NT_STATUS_IS_OK(status)) {
224 714 : *ret_tree = io.out.tree;
225 : }
226 748 : talloc_free(tmp_ctx);
227 748 : return status;
228 : }
|