Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : SMB client session context management functions
4 :
5 : Copyright (C) Andrew Tridgell 1994-2005
6 : Copyright (C) James Myers 2003 <myersjj@samba.org>
7 :
8 : This program is free software; you can redistribute it and/or modify
9 : it under the terms of the GNU General Public License as published by
10 : the Free Software Foundation; either version 3 of the License, or
11 : (at your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful,
14 : but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : GNU General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program. If not, see <http://www.gnu.org/licenses/>.
20 : */
21 :
22 : #include "includes.h"
23 : #include "libcli/raw/libcliraw.h"
24 : #include "libcli/raw/raw_proto.h"
25 : #include "system/filesys.h"
26 : #include "../libcli/smb/smbXcli_base.h"
27 :
28 : #define SETUP_REQUEST_SESSION(cmd, wct, buflen) do { \
29 : req = smbcli_request_setup_session(session, cmd, wct, buflen); \
30 : if (!req) return NULL; \
31 : } while (0)
32 :
33 :
34 : /****************************************************************************
35 : Initialize the session context
36 : ****************************************************************************/
37 925 : struct smbcli_session *smbcli_session_init(struct smbcli_transport *transport,
38 : TALLOC_CTX *parent_ctx, bool primary,
39 : struct smbcli_session_options options)
40 : {
41 : struct smbcli_session *session;
42 : uint16_t flags2;
43 : uint32_t capabilities;
44 :
45 925 : session = talloc_zero(parent_ctx, struct smbcli_session);
46 925 : if (!session) {
47 0 : return NULL;
48 : }
49 :
50 925 : if (primary) {
51 894 : session->transport = talloc_steal(session, transport);
52 : } else {
53 31 : session->transport = talloc_reference(session, transport);
54 : }
55 925 : session->pid = (uint32_t)getpid();
56 925 : session->vuid = UID_FIELD_INVALID;
57 925 : session->options = options;
58 :
59 : /*
60 : * for now session->vuid is still used by the callers, but we call:
61 : * smb1cli_session_set_id(session->smbXcli, session->vuid);
62 : * before using session->smbXcli, in future we should remove
63 : * session->vuid.
64 : */
65 925 : session->smbXcli = smbXcli_session_create(session, transport->conn);
66 925 : if (session->smbXcli == NULL) {
67 0 : talloc_free(session);
68 0 : return NULL;
69 : }
70 :
71 925 : capabilities = transport->negotiate.capabilities;
72 :
73 925 : flags2 = FLAGS2_LONG_PATH_COMPONENTS | FLAGS2_EXTENDED_ATTRIBUTES;
74 :
75 925 : if (capabilities & CAP_UNICODE) {
76 921 : flags2 |= FLAGS2_UNICODE_STRINGS;
77 : }
78 925 : if (capabilities & CAP_STATUS32) {
79 921 : flags2 |= FLAGS2_32_BIT_ERROR_CODES;
80 : }
81 925 : if (capabilities & CAP_EXTENDED_SECURITY) {
82 917 : flags2 |= FLAGS2_EXTENDED_SECURITY;
83 : }
84 925 : if (smb1cli_conn_signing_is_active(session->transport->conn)) {
85 31 : flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES;
86 : }
87 :
88 925 : session->flags2 = flags2;
89 :
90 925 : return session;
91 : }
92 :
93 : /****************************************************************************
94 : Perform a session setup (async send)
95 : ****************************************************************************/
96 1034 : struct smbcli_request *smb_raw_sesssetup_send(struct smbcli_session *session,
97 : union smb_sesssetup *parms)
98 : {
99 1034 : struct smbcli_request *req = NULL;
100 :
101 1034 : switch (parms->old.level) {
102 4 : case RAW_SESSSETUP_OLD:
103 4 : SETUP_REQUEST_SESSION(SMBsesssetupX, 10, 0);
104 4 : SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
105 4 : SSVAL(req->out.vwv, VWV(1), 0);
106 4 : SSVAL(req->out.vwv,VWV(2),parms->old.in.bufsize);
107 4 : SSVAL(req->out.vwv,VWV(3),parms->old.in.mpx_max);
108 4 : SSVAL(req->out.vwv,VWV(4),parms->old.in.vc_num);
109 4 : SIVAL(req->out.vwv,VWV(5),parms->old.in.sesskey);
110 4 : SSVAL(req->out.vwv,VWV(7),parms->old.in.password.length);
111 4 : SIVAL(req->out.vwv,VWV(8), 0); /* reserved */
112 4 : smbcli_req_append_blob(req, &parms->old.in.password);
113 4 : smbcli_req_append_string(req, parms->old.in.user, STR_TERMINATE);
114 4 : smbcli_req_append_string(req, parms->old.in.domain, STR_TERMINATE|STR_UPPER);
115 4 : smbcli_req_append_string(req, parms->old.in.os, STR_TERMINATE);
116 4 : smbcli_req_append_string(req, parms->old.in.lanman, STR_TERMINATE);
117 4 : break;
118 :
119 5 : case RAW_SESSSETUP_NT1:
120 5 : SETUP_REQUEST_SESSION(SMBsesssetupX, 13, 0);
121 5 : SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
122 5 : SSVAL(req->out.vwv, VWV(1), 0);
123 5 : SSVAL(req->out.vwv, VWV(2), parms->nt1.in.bufsize);
124 5 : SSVAL(req->out.vwv, VWV(3), parms->nt1.in.mpx_max);
125 5 : SSVAL(req->out.vwv, VWV(4), parms->nt1.in.vc_num);
126 5 : SIVAL(req->out.vwv, VWV(5), parms->nt1.in.sesskey);
127 5 : SSVAL(req->out.vwv, VWV(7), parms->nt1.in.password1.length);
128 5 : SSVAL(req->out.vwv, VWV(8), parms->nt1.in.password2.length);
129 5 : SIVAL(req->out.vwv, VWV(9), 0); /* reserved */
130 5 : SIVAL(req->out.vwv, VWV(11), parms->nt1.in.capabilities);
131 5 : smbcli_req_append_blob(req, &parms->nt1.in.password1);
132 5 : smbcli_req_append_blob(req, &parms->nt1.in.password2);
133 5 : smbcli_req_append_string(req, parms->nt1.in.user, STR_TERMINATE);
134 5 : smbcli_req_append_string(req, parms->nt1.in.domain, STR_TERMINATE|STR_UPPER);
135 5 : smbcli_req_append_string(req, parms->nt1.in.os, STR_TERMINATE);
136 5 : smbcli_req_append_string(req, parms->nt1.in.lanman, STR_TERMINATE);
137 5 : break;
138 :
139 1025 : case RAW_SESSSETUP_SPNEGO:
140 1025 : SETUP_REQUEST_SESSION(SMBsesssetupX, 12, 0);
141 1025 : SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
142 1025 : SSVAL(req->out.vwv, VWV(1), 0);
143 1025 : SSVAL(req->out.vwv, VWV(2), parms->spnego.in.bufsize);
144 1025 : SSVAL(req->out.vwv, VWV(3), parms->spnego.in.mpx_max);
145 1025 : SSVAL(req->out.vwv, VWV(4), parms->spnego.in.vc_num);
146 1025 : SIVAL(req->out.vwv, VWV(5), parms->spnego.in.sesskey);
147 1025 : SSVAL(req->out.vwv, VWV(7), parms->spnego.in.secblob.length);
148 1025 : SIVAL(req->out.vwv, VWV(8), 0); /* reserved */
149 1025 : SIVAL(req->out.vwv, VWV(10), parms->spnego.in.capabilities);
150 1025 : smbcli_req_append_blob(req, &parms->spnego.in.secblob);
151 1025 : smbcli_req_append_string(req, parms->spnego.in.os, STR_TERMINATE);
152 1025 : smbcli_req_append_string(req, parms->spnego.in.lanman, STR_TERMINATE);
153 1025 : smbcli_req_append_string(req, parms->spnego.in.workgroup, STR_TERMINATE);
154 1025 : break;
155 :
156 0 : case RAW_SESSSETUP_SMB2:
157 0 : return NULL;
158 : }
159 :
160 1034 : if (!smbcli_request_send(req)) {
161 0 : smbcli_request_destroy(req);
162 0 : return NULL;
163 : }
164 :
165 1034 : return req;
166 : }
167 :
168 :
169 : /****************************************************************************
170 : Perform a session setup (async recv)
171 : ****************************************************************************/
172 1034 : NTSTATUS smb_raw_sesssetup_recv(struct smbcli_request *req,
173 : TALLOC_CTX *mem_ctx,
174 : union smb_sesssetup *parms)
175 : {
176 : uint16_t len;
177 : uint8_t *p;
178 :
179 1034 : if (!smbcli_request_receive(req)) {
180 0 : return smbcli_request_destroy(req);
181 : }
182 :
183 1106 : if (!NT_STATUS_IS_OK(req->status) &&
184 115 : !NT_STATUS_EQUAL(req->status,NT_STATUS_MORE_PROCESSING_REQUIRED)) {
185 7 : return smbcli_request_destroy(req);
186 : }
187 :
188 1027 : switch (parms->old.level) {
189 0 : case RAW_SESSSETUP_OLD:
190 0 : SMBCLI_CHECK_WCT(req, 3);
191 0 : ZERO_STRUCT(parms->old.out);
192 0 : parms->old.out.vuid = SVAL(req->in.hdr, HDR_UID);
193 0 : parms->old.out.action = SVAL(req->in.vwv, VWV(2));
194 0 : p = req->in.data;
195 0 : if (p) {
196 0 : p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->old.out.os, p, -1, STR_TERMINATE);
197 0 : p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->old.out.lanman, p, -1, STR_TERMINATE);
198 0 : smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->old.out.domain, p, -1, STR_TERMINATE);
199 : }
200 83 : break;
201 :
202 5 : case RAW_SESSSETUP_NT1:
203 5 : SMBCLI_CHECK_WCT(req, 3);
204 5 : ZERO_STRUCT(parms->nt1.out);
205 5 : parms->nt1.out.vuid = SVAL(req->in.hdr, HDR_UID);
206 5 : parms->nt1.out.action = SVAL(req->in.vwv, VWV(2));
207 5 : p = req->in.data;
208 5 : if (p) {
209 5 : p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->nt1.out.os, p, -1, STR_TERMINATE);
210 5 : p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->nt1.out.lanman, p, -1, STR_TERMINATE);
211 5 : if (p < (req->in.data + req->in.data_size)) {
212 5 : smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->nt1.out.domain, p, -1, STR_TERMINATE);
213 : }
214 : }
215 5 : break;
216 :
217 1022 : case RAW_SESSSETUP_SPNEGO:
218 1022 : SMBCLI_CHECK_WCT(req, 4);
219 1022 : ZERO_STRUCT(parms->spnego.out);
220 1022 : parms->spnego.out.vuid = SVAL(req->in.hdr, HDR_UID);
221 1022 : parms->spnego.out.action = SVAL(req->in.vwv, VWV(2));
222 1022 : len = SVAL(req->in.vwv, VWV(3));
223 1022 : p = req->in.data;
224 1022 : if (!p) {
225 0 : break;
226 : }
227 :
228 1022 : parms->spnego.out.secblob = smbcli_req_pull_blob(&req->in.bufinfo, mem_ctx, p, len);
229 1022 : p += parms->spnego.out.secblob.length;
230 1022 : p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->spnego.out.os, p, -1, STR_TERMINATE);
231 1022 : p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->spnego.out.lanman, p, -1, STR_TERMINATE);
232 1022 : smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->spnego.out.workgroup, p, -1, STR_TERMINATE);
233 1022 : break;
234 :
235 0 : case RAW_SESSSETUP_SMB2:
236 0 : req->status = NT_STATUS_INTERNAL_ERROR;
237 0 : break;
238 : }
239 :
240 1027 : failed:
241 1027 : return smbcli_request_destroy(req);
242 : }
243 :
244 :
245 : /*
246 : Perform a session setup (sync interface)
247 : */
248 0 : NTSTATUS smb_raw_sesssetup(struct smbcli_session *session,
249 : TALLOC_CTX *mem_ctx, union smb_sesssetup *parms)
250 : {
251 0 : struct smbcli_request *req = smb_raw_sesssetup_send(session, parms);
252 0 : return smb_raw_sesssetup_recv(req, mem_ctx, parms);
253 : }
254 :
255 :
256 : /****************************************************************************
257 : Send a ulogoff (async send)
258 : *****************************************************************************/
259 20 : struct smbcli_request *smb_raw_ulogoff_send(struct smbcli_session *session)
260 : {
261 : struct smbcli_request *req;
262 :
263 20 : SETUP_REQUEST_SESSION(SMBulogoffX, 2, 0);
264 :
265 20 : SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
266 20 : SSVAL(req->out.vwv, VWV(1), 0);
267 :
268 20 : if (!smbcli_request_send(req)) {
269 0 : smbcli_request_destroy(req);
270 0 : return NULL;
271 : }
272 :
273 20 : return req;
274 : }
275 :
276 : /****************************************************************************
277 : Send a ulogoff (sync interface)
278 : *****************************************************************************/
279 20 : NTSTATUS smb_raw_ulogoff(struct smbcli_session *session)
280 : {
281 20 : struct smbcli_request *req = smb_raw_ulogoff_send(session);
282 20 : return smbcli_request_simple_recv(req);
283 : }
284 :
285 :
286 : /****************************************************************************
287 : Send a exit (async send)
288 : *****************************************************************************/
289 613 : struct smbcli_request *smb_raw_exit_send(struct smbcli_session *session)
290 : {
291 : struct smbcli_request *req;
292 :
293 613 : SETUP_REQUEST_SESSION(SMBexit, 0, 0);
294 :
295 613 : if (!smbcli_request_send(req)) {
296 0 : smbcli_request_destroy(req);
297 0 : return NULL;
298 : }
299 :
300 613 : return req;
301 : }
302 :
303 : /****************************************************************************
304 : Send a exit (sync interface)
305 : *****************************************************************************/
306 613 : _PUBLIC_ NTSTATUS smb_raw_exit(struct smbcli_session *session)
307 : {
308 613 : struct smbcli_request *req = smb_raw_exit_send(session);
309 613 : return smbcli_request_simple_recv(req);
310 : }
|