2872c371c05307ac5a145d65bf74e7a006605608
[metze/samba/wip.git] / source3 / libsmb / smb2cli_tcon.c
1 /*
2    Unix SMB/CIFS implementation.
3    smb2 lib
4    Copyright (C) Volker Lendecke 2011
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "includes.h"
21 #include "client.h"
22 #include "async_smb.h"
23 #include "smb2cli_base.h"
24 #include "smb2cli.h"
25 #include "libsmb/proto.h"
26 #include "lib/util/tevent_ntstatus.h"
27
28 struct smb2cli_tcon_state {
29         struct cli_state *cli;
30         uint8_t fixed[8];
31 };
32
33 static void smb2cli_tcon_done(struct tevent_req *subreq);
34
35 struct tevent_req *smb2cli_tcon_send(TALLOC_CTX *mem_ctx,
36                                      struct tevent_context *ev,
37                                      struct cli_state *cli,
38                                      const char *share)
39 {
40         struct tevent_req *req, *subreq;
41         struct smb2cli_tcon_state *state;
42         uint8_t *fixed;
43         char srv_ip[INET6_ADDRSTRLEN];
44         const char *tcon_share;
45         uint8_t *dyn;
46         size_t dyn_len;
47
48         req = tevent_req_create(mem_ctx, &state, struct smb2cli_tcon_state);
49         if (req == NULL) {
50                 return NULL;
51         }
52         state->cli = cli;
53
54         print_sockaddr(srv_ip, sizeof(srv_ip), cli_state_remote_sockaddr(cli));
55
56         tcon_share = talloc_asprintf(talloc_tos(), "\\\\%s\\%s",
57                                      srv_ip, share);
58         if (tevent_req_nomem(tcon_share, req)) {
59                 return tevent_req_post(req, ev);
60         }
61         if (!convert_string_talloc(state, CH_UNIX, CH_UTF16,
62                                    tcon_share, talloc_get_size(tcon_share),
63                                    &dyn, &dyn_len)) {
64                 tevent_req_oom(req);
65                 return tevent_req_post(req, ev);
66         }
67
68         fixed = state->fixed;
69         SSVAL(fixed, 0, 9);
70         SSVAL(fixed, 4, SMB2_HDR_BODY + 8);
71         SSVAL(fixed, 6, dyn_len);
72
73         subreq = smb2cli_req_send(state, ev, cli, SMB2_OP_TCON,
74                                   0, 0, /* flags */
75                                   cli->smb2.pid,
76                                   0, /* tid */
77                                   cli->smb2.uid,
78                                   state->fixed, sizeof(state->fixed),
79                                   dyn, dyn_len);
80         if (tevent_req_nomem(subreq, req)) {
81                 return tevent_req_post(req, ev);
82         }
83         tevent_req_set_callback(subreq, smb2cli_tcon_done, req);
84         return req;
85 }
86
87 static void smb2cli_tcon_done(struct tevent_req *subreq)
88 {
89         struct tevent_req *req = tevent_req_callback_data(
90                 subreq, struct tevent_req);
91         struct smb2cli_tcon_state *state = tevent_req_data(
92                 req, struct smb2cli_tcon_state);
93         struct cli_state *cli = state->cli;
94         NTSTATUS status;
95         struct iovec *iov;
96         uint8_t *body;
97
98         status = smb2cli_req_recv(subreq, talloc_tos(), &iov, 16);
99         if (!NT_STATUS_IS_OK(status)) {
100                 TALLOC_FREE(subreq);
101                 tevent_req_nterror(req, status);
102                 return;
103         }
104
105         cli->smb2.tid = IVAL(iov[0].iov_base, SMB2_HDR_TID);
106
107         body = (uint8_t *)iov[1].iov_base;
108         cli->smb2.share_type            = CVAL(body, 2);
109         cli->smb2.share_flags           = IVAL(body, 4);
110         cli->capabilities               = IVAL(body, 8);
111         cli->smb2.maximal_access        = IVAL(body, 12);
112
113         TALLOC_FREE(subreq);
114         tevent_req_done(req);
115 }
116
117 NTSTATUS smb2cli_tcon_recv(struct tevent_req *req)
118 {
119         return tevent_req_simple_recv_ntstatus(req);
120 }
121
122 NTSTATUS smb2cli_tcon(struct cli_state *cli, const char *share)
123 {
124         TALLOC_CTX *frame = talloc_stackframe();
125         struct event_context *ev;
126         struct tevent_req *req;
127         NTSTATUS status = NT_STATUS_NO_MEMORY;
128
129         if (cli_has_async_calls(cli)) {
130                 /*
131                  * Can't use sync call while an async call is in flight
132                  */
133                 status = NT_STATUS_INVALID_PARAMETER;
134                 goto fail;
135         }
136         ev = event_context_init(frame);
137         if (ev == NULL) {
138                 goto fail;
139         }
140         req = smb2cli_tcon_send(frame, ev, cli, share);
141         if (req == NULL) {
142                 goto fail;
143         }
144         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
145                 goto fail;
146         }
147         status = smb2cli_tcon_recv(req);
148  fail:
149         TALLOC_FREE(frame);
150         return status;
151 }
152
153 struct smb2cli_tdis_state {
154         uint8_t fixed[4];
155 };
156
157 static void smb2cli_tdis_done(struct tevent_req *subreq);
158
159 struct tevent_req *smb2cli_tdis_send(TALLOC_CTX *mem_ctx,
160                                       struct tevent_context *ev,
161                                       struct cli_state *cli)
162 {
163         struct tevent_req *req, *subreq;
164         struct smb2cli_tdis_state *state;
165
166         req = tevent_req_create(mem_ctx, &state,
167                                 struct smb2cli_tdis_state);
168         if (req == NULL) {
169                 return NULL;
170         }
171         SSVAL(state->fixed, 0, 4);
172
173         subreq = smb2cli_req_send(state, ev, cli, SMB2_OP_TDIS,
174                                   0, 0, /* flags */
175                                   cli->smb2.pid,
176                                   cli->smb2.tid,
177                                   cli->smb2.uid,
178                                   state->fixed, sizeof(state->fixed),
179                                   NULL, 0);
180         if (tevent_req_nomem(subreq, req)) {
181                 return tevent_req_post(req, ev);
182         }
183         tevent_req_set_callback(subreq, smb2cli_tdis_done, req);
184         return req;
185 }
186
187 static void smb2cli_tdis_done(struct tevent_req *subreq)
188 {
189         struct tevent_req *req =
190                 tevent_req_callback_data(subreq,
191                 struct tevent_req);
192         NTSTATUS status;
193         struct iovec *iov;
194
195         status = smb2cli_req_recv(subreq, talloc_tos(), &iov, 4);
196         TALLOC_FREE(subreq);
197         if (tevent_req_nterror(req, status)) {
198                 return;
199         }
200         tevent_req_done(req);
201 }
202
203 NTSTATUS smb2cli_tdis_recv(struct tevent_req *req)
204 {
205         return tevent_req_simple_recv_ntstatus(req);
206 }
207
208 NTSTATUS smb2cli_tdis(struct cli_state *cli)
209 {
210         TALLOC_CTX *frame = talloc_stackframe();
211         struct event_context *ev;
212         struct tevent_req *req;
213         NTSTATUS status = NT_STATUS_NO_MEMORY;
214
215         if (cli_has_async_calls(cli)) {
216                 /*
217                  * Can't use sync call while an async call is in flight
218                  */
219                 status = NT_STATUS_INVALID_PARAMETER;
220                 goto fail;
221         }
222         ev = event_context_init(frame);
223         if (ev == NULL) {
224                 goto fail;
225         }
226         req = smb2cli_tdis_send(frame, ev, cli);
227         if (req == NULL) {
228                 goto fail;
229         }
230         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
231                 goto fail;
232         }
233         status = smb2cli_tdis_recv(req);
234  fail:
235         TALLOC_FREE(frame);
236         return status;
237 }