Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : client connect/disconnect routines
4 : Copyright (C) Andrew Tridgell 1994-1998
5 : Copyright (C) Andrew Bartlett 2001-2003
6 : Copyright (C) Volker Lendecke 2011
7 : Copyright (C) Jeremy Allison 2011
8 : Copyright (C) Stefan Metzmacher 2016
9 :
10 : This program is free software; you can redistribute it and/or modify
11 : it under the terms of the GNU General Public License as published by
12 : the Free Software Foundation; either version 3 of the License, or
13 : (at your option) any later version.
14 :
15 : This program is distributed in the hope that it will be useful,
16 : but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : GNU General Public License for more details.
19 :
20 : You should have received a copy of the GNU General Public License
21 : along with this program. If not, see <http://www.gnu.org/licenses/>.
22 : */
23 :
24 : #include "includes.h"
25 : #include "system/network.h"
26 : #include "../lib/util/tevent_ntstatus.h"
27 : #include "../libcli/smb/smb_common.h"
28 : #include "../libcli/smb/smbXcli_base.h"
29 :
30 :
31 : struct smb1cli_session_setup_lm21_state {
32 : struct smbXcli_session *session;
33 : uint16_t vwv[10];
34 : struct iovec *recv_iov;
35 : uint16_t out_session_id;
36 : uint16_t out_action;
37 : char *out_native_os;
38 : char *out_native_lm;
39 : };
40 :
41 : static void smb1cli_session_setup_lm21_done(struct tevent_req *subreq);
42 :
43 24 : struct tevent_req *smb1cli_session_setup_lm21_send(TALLOC_CTX *mem_ctx,
44 : struct tevent_context *ev,
45 : struct smbXcli_conn *conn,
46 : uint32_t timeout_msec,
47 : uint32_t pid,
48 : struct smbXcli_session *session,
49 : uint16_t in_buf_size,
50 : uint16_t in_mpx_max,
51 : uint16_t in_vc_num,
52 : uint32_t in_sess_key,
53 : const char *in_user,
54 : const char *in_domain,
55 : const DATA_BLOB in_apassword,
56 : const char *in_native_os,
57 : const char *in_native_lm)
58 : {
59 24 : struct tevent_req *req = NULL;
60 24 : struct smb1cli_session_setup_lm21_state *state = NULL;
61 24 : struct tevent_req *subreq = NULL;
62 24 : uint16_t *vwv = NULL;
63 24 : uint8_t *bytes = NULL;
64 :
65 24 : req = tevent_req_create(mem_ctx, &state,
66 : struct smb1cli_session_setup_lm21_state);
67 24 : if (req == NULL) {
68 0 : return NULL;
69 : }
70 24 : state->session = session;
71 24 : vwv = state->vwv;
72 :
73 24 : if (in_user == NULL) {
74 0 : tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
75 0 : return tevent_req_post(req, ev);
76 : }
77 :
78 24 : if (in_domain == NULL) {
79 0 : tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
80 0 : return tevent_req_post(req, ev);
81 : }
82 :
83 24 : if (in_apassword.length > UINT16_MAX) {
84 0 : tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
85 0 : return tevent_req_post(req, ev);
86 : }
87 :
88 24 : if (in_native_os == NULL && in_native_lm != NULL) {
89 0 : tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
90 0 : return tevent_req_post(req, ev);
91 : }
92 :
93 24 : SCVAL(vwv+0, 0, 0xff);
94 24 : SCVAL(vwv+0, 1, 0);
95 24 : SSVAL(vwv+1, 0, 0);
96 24 : SSVAL(vwv+2, 0, in_buf_size);
97 24 : SSVAL(vwv+3, 0, in_mpx_max);
98 24 : SSVAL(vwv+4, 0, in_vc_num);
99 24 : SIVAL(vwv+5, 0, in_sess_key);
100 24 : SSVAL(vwv+7, 0, in_apassword.length);
101 24 : SSVAL(vwv+8, 0, 0); /* reserved */
102 24 : SSVAL(vwv+9, 0, 0); /* reserved */
103 :
104 24 : bytes = talloc_array(state, uint8_t,
105 : in_apassword.length);
106 24 : if (tevent_req_nomem(bytes, req)) {
107 0 : return tevent_req_post(req, ev);
108 : }
109 24 : if (in_apassword.length != 0) {
110 14 : memcpy(bytes,
111 14 : in_apassword.data,
112 14 : in_apassword.length);
113 : }
114 :
115 24 : bytes = smb_bytes_push_str(bytes,
116 24 : smbXcli_conn_use_unicode(conn),
117 24 : in_user, strlen(in_user)+1,
118 : NULL);
119 24 : bytes = smb_bytes_push_str(bytes,
120 24 : smbXcli_conn_use_unicode(conn),
121 24 : in_domain, strlen(in_domain)+1,
122 : NULL);
123 24 : if (in_native_os != NULL) {
124 24 : bytes = smb_bytes_push_str(bytes,
125 24 : smbXcli_conn_use_unicode(conn),
126 24 : in_native_os, strlen(in_native_os)+1,
127 : NULL);
128 : }
129 24 : if (in_native_lm != NULL) {
130 24 : bytes = smb_bytes_push_str(bytes,
131 24 : smbXcli_conn_use_unicode(conn),
132 24 : in_native_lm, strlen(in_native_lm)+1,
133 : NULL);
134 : }
135 24 : if (tevent_req_nomem(bytes, req)) {
136 0 : return tevent_req_post(req, ev);
137 : }
138 :
139 24 : subreq = smb1cli_req_send(state, ev, conn,
140 : SMBsesssetupX,
141 : 0, /* additional_flags */
142 : 0, /* clear_flags */
143 : 0, /* additional_flags2 */
144 : 0, /* clear_flags2 */
145 : timeout_msec,
146 : pid,
147 : NULL, /* tcon */
148 : session,
149 : 10, /* wct */
150 : vwv,
151 24 : talloc_get_size(bytes),
152 : bytes);
153 24 : if (tevent_req_nomem(subreq, req)) {
154 0 : return tevent_req_post(req, ev);
155 : }
156 24 : tevent_req_set_callback(subreq, smb1cli_session_setup_lm21_done, req);
157 :
158 24 : return req;
159 : }
160 :
161 24 : static void smb1cli_session_setup_lm21_done(struct tevent_req *subreq)
162 : {
163 0 : struct tevent_req *req =
164 24 : tevent_req_callback_data(subreq,
165 : struct tevent_req);
166 0 : struct smb1cli_session_setup_lm21_state *state =
167 24 : tevent_req_data(req,
168 : struct smb1cli_session_setup_lm21_state);
169 0 : NTSTATUS status;
170 24 : uint8_t *inhdr = NULL;
171 0 : uint8_t wct;
172 24 : uint16_t *vwv = NULL;
173 0 : uint32_t num_bytes;
174 24 : uint8_t *bytes = NULL;
175 24 : const uint8_t *p = NULL;
176 24 : size_t ret = 0;
177 0 : uint16_t flags2;
178 24 : bool use_unicode = false;
179 24 : struct smb1cli_req_expected_response expected[] = {
180 : {
181 : .status = NT_STATUS_OK,
182 : .wct = 3,
183 : },
184 : };
185 :
186 24 : status = smb1cli_req_recv(subreq, state,
187 : &state->recv_iov,
188 : &inhdr,
189 : &wct,
190 : &vwv,
191 : NULL, /* pvwv_offset */
192 : &num_bytes,
193 : &bytes,
194 : NULL, /* pbytes_offset */
195 : NULL, /* pinbuf */
196 : expected, ARRAY_SIZE(expected));
197 24 : TALLOC_FREE(subreq);
198 24 : if (tevent_req_nterror(req, status)) {
199 0 : return;
200 : }
201 :
202 24 : flags2 = SVAL(inhdr, HDR_FLG2);
203 24 : if (flags2 & FLAGS2_UNICODE_STRINGS) {
204 0 : use_unicode = true;
205 : }
206 :
207 24 : state->out_session_id = SVAL(inhdr, HDR_UID);
208 24 : state->out_action = SVAL(vwv+2, 0);
209 :
210 24 : p = bytes;
211 :
212 24 : status = smb_bytes_pull_str(state, &state->out_native_os,
213 : use_unicode, bytes, num_bytes,
214 : p, &ret);
215 24 : if (tevent_req_nterror(req, status)) {
216 0 : return;
217 : }
218 24 : p += ret;
219 :
220 24 : status = smb_bytes_pull_str(state, &state->out_native_lm,
221 : use_unicode, bytes, num_bytes,
222 : p, &ret);
223 24 : if (tevent_req_nterror(req, status)) {
224 0 : return;
225 : }
226 :
227 24 : smb1cli_session_set_id(state->session, state->out_session_id);
228 24 : smb1cli_session_set_action(state->session, state->out_action);
229 :
230 24 : tevent_req_done(req);
231 : }
232 :
233 24 : NTSTATUS smb1cli_session_setup_lm21_recv(struct tevent_req *req,
234 : TALLOC_CTX *mem_ctx,
235 : char **out_native_os,
236 : char **out_native_lm)
237 : {
238 0 : struct smb1cli_session_setup_lm21_state *state =
239 24 : tevent_req_data(req,
240 : struct smb1cli_session_setup_lm21_state);
241 0 : NTSTATUS status;
242 :
243 24 : if (tevent_req_is_nterror(req, &status)) {
244 0 : tevent_req_received(req);
245 0 : return status;
246 : }
247 :
248 24 : if (out_native_os != NULL) {
249 24 : *out_native_os = talloc_move(mem_ctx, &state->out_native_os);
250 : }
251 :
252 24 : if (out_native_lm != NULL) {
253 24 : *out_native_lm = talloc_move(mem_ctx, &state->out_native_lm);
254 : }
255 :
256 24 : tevent_req_received(req);
257 24 : return NT_STATUS_OK;
258 : }
259 :
260 : struct smb1cli_session_setup_nt1_state {
261 : struct smbXcli_session *session;
262 : uint16_t vwv[13];
263 : struct iovec *recv_iov;
264 : uint8_t *inbuf;
265 : uint16_t out_session_id;
266 : uint16_t out_action;
267 : char *out_native_os;
268 : char *out_native_lm;
269 : char *out_primary_domain;
270 : };
271 :
272 : static void smb1cli_session_setup_nt1_done(struct tevent_req *subreq);
273 :
274 65 : struct tevent_req *smb1cli_session_setup_nt1_send(TALLOC_CTX *mem_ctx,
275 : struct tevent_context *ev,
276 : struct smbXcli_conn *conn,
277 : uint32_t timeout_msec,
278 : uint32_t pid,
279 : struct smbXcli_session *session,
280 : uint16_t in_buf_size,
281 : uint16_t in_mpx_max,
282 : uint16_t in_vc_num,
283 : uint32_t in_sess_key,
284 : const char *in_user,
285 : const char *in_domain,
286 : const DATA_BLOB in_apassword,
287 : const DATA_BLOB in_upassword,
288 : uint32_t in_capabilities,
289 : const char *in_native_os,
290 : const char *in_native_lm)
291 : {
292 65 : struct tevent_req *req = NULL;
293 65 : struct smb1cli_session_setup_nt1_state *state = NULL;
294 65 : struct tevent_req *subreq = NULL;
295 65 : uint16_t *vwv = NULL;
296 65 : uint8_t *bytes = NULL;
297 65 : size_t align_upassword = 0;
298 65 : size_t apassword_ofs = 0;
299 65 : size_t upassword_ofs = 0;
300 :
301 65 : req = tevent_req_create(mem_ctx, &state,
302 : struct smb1cli_session_setup_nt1_state);
303 65 : if (req == NULL) {
304 0 : return NULL;
305 : }
306 65 : state->session = session;
307 65 : vwv = state->vwv;
308 :
309 65 : if (in_user == NULL) {
310 0 : tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
311 0 : return tevent_req_post(req, ev);
312 : }
313 :
314 65 : if (in_domain == NULL) {
315 0 : tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
316 0 : return tevent_req_post(req, ev);
317 : }
318 :
319 65 : if (in_apassword.length > UINT16_MAX) {
320 0 : tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
321 0 : return tevent_req_post(req, ev);
322 : }
323 :
324 65 : if (in_upassword.length > UINT16_MAX) {
325 0 : tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
326 0 : return tevent_req_post(req, ev);
327 : }
328 :
329 65 : if (in_native_os == NULL && in_native_lm != NULL) {
330 0 : tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
331 0 : return tevent_req_post(req, ev);
332 : }
333 :
334 65 : SCVAL(vwv+0, 0, 0xff);
335 65 : SCVAL(vwv+0, 1, 0);
336 65 : SSVAL(vwv+1, 0, 0);
337 65 : SSVAL(vwv+2, 0, in_buf_size);
338 65 : SSVAL(vwv+3, 0, in_mpx_max);
339 65 : SSVAL(vwv+4, 0, in_vc_num);
340 65 : SIVAL(vwv+5, 0, in_sess_key);
341 65 : SSVAL(vwv+7, 0, in_apassword.length);
342 65 : SSVAL(vwv+8, 0, in_upassword.length);
343 65 : SSVAL(vwv+9, 0, 0); /* reserved */
344 65 : SSVAL(vwv+10, 0, 0); /* reserved */
345 65 : SIVAL(vwv+11, 0, in_capabilities);
346 :
347 65 : if (in_apassword.length == 0 && in_upassword.length > 0) {
348 : /*
349 : * This is plaintext auth with a unicode password,
350 : * we need to align the buffer.
351 : *
352 : * This is what smbclient and Windows XP send as
353 : * a client. And what smbd expects.
354 : *
355 : * But it doesn't follow [MS-CIFS] (v20160714)
356 : * 2.2.4.53.1 SMB_COM_SESSION_SETUP_ANDX Request:
357 : *
358 : * ...
359 : *
360 : * If SMB_FLAGS2_UNICODE is set (1), the value of OEMPasswordLen
361 : * MUST be 0x0000 and the password MUST be encoded using
362 : * UTF-16LE Unicode. Padding MUST NOT be added to
363 : * align this plaintext Unicode string to a word boundary.
364 : *
365 : * ...
366 : */
367 0 : uint16_t security_mode = smb1cli_conn_server_security_mode(conn);
368 :
369 0 : if (!(security_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)) {
370 0 : align_upassword = 1;
371 : }
372 : }
373 :
374 65 : bytes = talloc_array(state, uint8_t,
375 : in_apassword.length +
376 : align_upassword +
377 : in_upassword.length);
378 65 : if (tevent_req_nomem(bytes, req)) {
379 0 : return tevent_req_post(req, ev);
380 : }
381 65 : if (in_apassword.length != 0) {
382 42 : memcpy(bytes + apassword_ofs,
383 42 : in_apassword.data,
384 42 : in_apassword.length);
385 42 : upassword_ofs += in_apassword.length;
386 : }
387 65 : if (align_upassword != 0) {
388 0 : memset(bytes + upassword_ofs, 0, align_upassword);
389 0 : upassword_ofs += align_upassword;
390 : }
391 65 : if (in_upassword.length != 0) {
392 42 : memcpy(bytes + upassword_ofs,
393 42 : in_upassword.data,
394 42 : in_upassword.length);
395 : }
396 :
397 65 : bytes = smb_bytes_push_str(bytes,
398 65 : smbXcli_conn_use_unicode(conn),
399 65 : in_user, strlen(in_user)+1,
400 : NULL);
401 65 : bytes = smb_bytes_push_str(bytes,
402 65 : smbXcli_conn_use_unicode(conn),
403 65 : in_domain, strlen(in_domain)+1,
404 : NULL);
405 65 : if (in_native_os != NULL) {
406 65 : bytes = smb_bytes_push_str(bytes,
407 65 : smbXcli_conn_use_unicode(conn),
408 65 : in_native_os, strlen(in_native_os)+1,
409 : NULL);
410 : }
411 65 : if (in_native_lm != NULL) {
412 65 : bytes = smb_bytes_push_str(bytes,
413 65 : smbXcli_conn_use_unicode(conn),
414 65 : in_native_lm, strlen(in_native_lm)+1,
415 : NULL);
416 : }
417 65 : if (tevent_req_nomem(bytes, req)) {
418 0 : return tevent_req_post(req, ev);
419 : }
420 :
421 65 : subreq = smb1cli_req_send(state, ev, conn,
422 : SMBsesssetupX,
423 : 0, /* additional_flags */
424 : 0, /* clear_flags */
425 : 0, /* additional_flags2 */
426 : 0, /* clear_flags2 */
427 : timeout_msec,
428 : pid,
429 : NULL, /* tcon */
430 : session,
431 : 13, /* wct */
432 : vwv,
433 65 : talloc_get_size(bytes),
434 : bytes);
435 65 : if (tevent_req_nomem(subreq, req)) {
436 0 : return tevent_req_post(req, ev);
437 : }
438 65 : tevent_req_set_callback(subreq, smb1cli_session_setup_nt1_done, req);
439 :
440 65 : return req;
441 : }
442 :
443 65 : static void smb1cli_session_setup_nt1_done(struct tevent_req *subreq)
444 : {
445 0 : struct tevent_req *req =
446 65 : tevent_req_callback_data(subreq,
447 : struct tevent_req);
448 0 : struct smb1cli_session_setup_nt1_state *state =
449 65 : tevent_req_data(req,
450 : struct smb1cli_session_setup_nt1_state);
451 0 : NTSTATUS status;
452 65 : uint8_t *inhdr = NULL;
453 0 : uint8_t wct;
454 65 : uint16_t *vwv = NULL;
455 0 : uint32_t num_bytes;
456 65 : uint8_t *bytes = NULL;
457 65 : const uint8_t *p = NULL;
458 65 : size_t ret = 0;
459 0 : uint16_t flags2;
460 65 : bool use_unicode = false;
461 65 : struct smb1cli_req_expected_response expected[] = {
462 : {
463 : .status = NT_STATUS_OK,
464 : .wct = 3,
465 : },
466 : };
467 :
468 65 : status = smb1cli_req_recv(subreq, state,
469 : &state->recv_iov,
470 : &inhdr,
471 : &wct,
472 : &vwv,
473 : NULL, /* pvwv_offset */
474 : &num_bytes,
475 : &bytes,
476 : NULL, /* pbytes_offset */
477 : &state->inbuf,
478 : expected, ARRAY_SIZE(expected));
479 65 : TALLOC_FREE(subreq);
480 65 : if (tevent_req_nterror(req, status)) {
481 4 : return;
482 : }
483 :
484 61 : flags2 = SVAL(inhdr, HDR_FLG2);
485 61 : if (flags2 & FLAGS2_UNICODE_STRINGS) {
486 61 : use_unicode = true;
487 : }
488 :
489 61 : state->out_session_id = SVAL(inhdr, HDR_UID);
490 61 : state->out_action = SVAL(vwv+2, 0);
491 :
492 61 : p = bytes;
493 :
494 61 : status = smb_bytes_pull_str(state, &state->out_native_os,
495 : use_unicode, bytes, num_bytes,
496 : p, &ret);
497 61 : if (tevent_req_nterror(req, status)) {
498 0 : return;
499 : }
500 61 : p += ret;
501 :
502 61 : status = smb_bytes_pull_str(state, &state->out_native_lm,
503 : use_unicode, bytes, num_bytes,
504 : p, &ret);
505 61 : if (tevent_req_nterror(req, status)) {
506 0 : return;
507 : }
508 61 : p += ret;
509 :
510 61 : status = smb_bytes_pull_str(state, &state->out_primary_domain,
511 : use_unicode, bytes, num_bytes,
512 : p, &ret);
513 61 : if (tevent_req_nterror(req, status)) {
514 0 : return;
515 : }
516 :
517 61 : smb1cli_session_set_id(state->session, state->out_session_id);
518 61 : smb1cli_session_set_action(state->session, state->out_action);
519 :
520 61 : tevent_req_done(req);
521 : }
522 :
523 65 : NTSTATUS smb1cli_session_setup_nt1_recv(struct tevent_req *req,
524 : TALLOC_CTX *mem_ctx,
525 : struct iovec **precv_iov,
526 : const uint8_t **precv_inbuf,
527 : char **out_native_os,
528 : char **out_native_lm,
529 : char **out_primary_domain)
530 : {
531 0 : struct smb1cli_session_setup_nt1_state *state =
532 65 : tevent_req_data(req,
533 : struct smb1cli_session_setup_nt1_state);
534 0 : NTSTATUS status;
535 65 : struct iovec *recv_iov = NULL;
536 :
537 65 : if (tevent_req_is_nterror(req, &status)) {
538 4 : tevent_req_received(req);
539 4 : return status;
540 : }
541 :
542 61 : recv_iov = talloc_move(mem_ctx, &state->recv_iov);
543 61 : if (precv_iov != NULL) {
544 61 : *precv_iov = recv_iov;
545 : }
546 61 : if (precv_inbuf != NULL) {
547 61 : *precv_inbuf = state->inbuf;
548 : }
549 :
550 61 : if (out_native_os != NULL) {
551 61 : *out_native_os = talloc_move(mem_ctx, &state->out_native_os);
552 : }
553 :
554 61 : if (out_native_lm != NULL) {
555 61 : *out_native_lm = talloc_move(mem_ctx, &state->out_native_lm);
556 : }
557 :
558 61 : if (out_primary_domain != NULL) {
559 61 : *out_primary_domain = talloc_move(mem_ctx,
560 : &state->out_primary_domain);
561 : }
562 :
563 61 : tevent_req_received(req);
564 61 : return NT_STATUS_OK;
565 : }
566 :
567 : struct smb1cli_session_setup_ext_state {
568 : struct smbXcli_session *session;
569 : uint16_t vwv[12];
570 : struct iovec *recv_iov;
571 : uint8_t *inbuf;
572 : NTSTATUS status;
573 : uint16_t out_session_id;
574 : uint16_t out_action;
575 : DATA_BLOB out_security_blob;
576 : char *out_native_os;
577 : char *out_native_lm;
578 : };
579 :
580 : static void smb1cli_session_setup_ext_done(struct tevent_req *subreq);
581 :
582 7624 : struct tevent_req *smb1cli_session_setup_ext_send(TALLOC_CTX *mem_ctx,
583 : struct tevent_context *ev,
584 : struct smbXcli_conn *conn,
585 : uint32_t timeout_msec,
586 : uint32_t pid,
587 : struct smbXcli_session *session,
588 : uint16_t in_buf_size,
589 : uint16_t in_mpx_max,
590 : uint16_t in_vc_num,
591 : uint32_t in_sess_key,
592 : const DATA_BLOB in_security_blob,
593 : uint32_t in_capabilities,
594 : const char *in_native_os,
595 : const char *in_native_lm)
596 : {
597 7624 : struct tevent_req *req = NULL;
598 7624 : struct smb1cli_session_setup_ext_state *state = NULL;
599 7624 : struct tevent_req *subreq = NULL;
600 7624 : uint16_t *vwv = NULL;
601 7624 : uint8_t *bytes = NULL;
602 :
603 7624 : req = tevent_req_create(mem_ctx, &state,
604 : struct smb1cli_session_setup_ext_state);
605 7624 : if (req == NULL) {
606 0 : return NULL;
607 : }
608 7624 : state->session = session;
609 7624 : vwv = state->vwv;
610 :
611 7624 : if (in_security_blob.length > UINT16_MAX) {
612 0 : tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
613 0 : return tevent_req_post(req, ev);
614 : }
615 :
616 7624 : if (in_native_os == NULL && in_native_lm != NULL) {
617 0 : tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
618 0 : return tevent_req_post(req, ev);
619 : }
620 :
621 7624 : SCVAL(vwv+0, 0, 0xff);
622 7624 : SCVAL(vwv+0, 1, 0);
623 7624 : SSVAL(vwv+1, 0, 0);
624 7624 : SSVAL(vwv+2, 0, in_buf_size);
625 7624 : SSVAL(vwv+3, 0, in_mpx_max);
626 7624 : SSVAL(vwv+4, 0, in_vc_num);
627 7624 : SIVAL(vwv+5, 0, in_sess_key);
628 7624 : SSVAL(vwv+7, 0, in_security_blob.length);
629 7624 : SSVAL(vwv+8, 0, 0); /* reserved */
630 7624 : SSVAL(vwv+9, 0, 0); /* reserved */
631 7624 : SIVAL(vwv+10, 0, in_capabilities);
632 :
633 7624 : bytes = talloc_array(state, uint8_t,
634 : in_security_blob.length);
635 7624 : if (tevent_req_nomem(bytes, req)) {
636 0 : return tevent_req_post(req, ev);
637 : }
638 7624 : if (in_security_blob.length != 0) {
639 7624 : memcpy(bytes,
640 7624 : in_security_blob.data,
641 7624 : in_security_blob.length);
642 : }
643 :
644 7624 : if (in_native_os != NULL) {
645 7624 : bytes = smb_bytes_push_str(bytes,
646 7624 : smbXcli_conn_use_unicode(conn),
647 7624 : in_native_os, strlen(in_native_os)+1,
648 : NULL);
649 : }
650 7624 : if (in_native_lm != NULL) {
651 7624 : bytes = smb_bytes_push_str(bytes,
652 7624 : smbXcli_conn_use_unicode(conn),
653 7624 : in_native_lm, strlen(in_native_lm)+1,
654 : NULL);
655 : }
656 7624 : if (tevent_req_nomem(bytes, req)) {
657 0 : return tevent_req_post(req, ev);
658 : }
659 :
660 7624 : subreq = smb1cli_req_send(state, ev, conn,
661 : SMBsesssetupX,
662 : 0, /* additional_flags */
663 : 0, /* clear_flags */
664 : 0, /* additional_flags2 */
665 : 0, /* clear_flags2 */
666 : timeout_msec,
667 : pid,
668 : NULL, /* tcon */
669 : session,
670 : 12, /* wct */
671 : vwv,
672 7624 : talloc_get_size(bytes),
673 : bytes);
674 7624 : if (tevent_req_nomem(subreq, req)) {
675 0 : return tevent_req_post(req, ev);
676 : }
677 7624 : tevent_req_set_callback(subreq, smb1cli_session_setup_ext_done, req);
678 :
679 7624 : return req;
680 : }
681 :
682 7624 : static void smb1cli_session_setup_ext_done(struct tevent_req *subreq)
683 : {
684 0 : struct tevent_req *req =
685 7624 : tevent_req_callback_data(subreq,
686 : struct tevent_req);
687 0 : struct smb1cli_session_setup_ext_state *state =
688 7624 : tevent_req_data(req,
689 : struct smb1cli_session_setup_ext_state);
690 0 : NTSTATUS status;
691 7624 : uint8_t *inhdr = NULL;
692 0 : uint8_t wct;
693 7624 : uint16_t *vwv = NULL;
694 0 : uint32_t num_bytes;
695 7624 : uint8_t *bytes = NULL;
696 7624 : const uint8_t *p = NULL;
697 7624 : size_t ret = 0;
698 0 : uint16_t flags2;
699 7624 : uint16_t out_security_blob_length = 0;
700 7624 : bool use_unicode = false;
701 7624 : struct smb1cli_req_expected_response expected[] = {
702 : {
703 : .status = NT_STATUS_OK,
704 : .wct = 4,
705 : },
706 : {
707 : .status = NT_STATUS_MORE_PROCESSING_REQUIRED,
708 : .wct = 4,
709 : },
710 : };
711 :
712 7624 : status = smb1cli_req_recv(subreq, state,
713 : &state->recv_iov,
714 : &inhdr,
715 : &wct,
716 : &vwv,
717 : NULL, /* pvwv_offset */
718 : &num_bytes,
719 : &bytes,
720 : NULL, /* pbytes_offset */
721 : &state->inbuf,
722 : expected, ARRAY_SIZE(expected));
723 7624 : TALLOC_FREE(subreq);
724 7624 : state->status = status;
725 7624 : if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
726 3801 : status = NT_STATUS_OK;
727 : }
728 7624 : if (tevent_req_nterror(req, status)) {
729 44 : return;
730 : }
731 :
732 7580 : flags2 = SVAL(inhdr, HDR_FLG2);
733 7580 : if (flags2 & FLAGS2_UNICODE_STRINGS) {
734 7580 : use_unicode = true;
735 : }
736 :
737 7580 : state->out_session_id = SVAL(inhdr, HDR_UID);
738 7580 : state->out_action = SVAL(vwv+2, 0);
739 7580 : out_security_blob_length = SVAL(vwv+3, 0);
740 :
741 7580 : if (out_security_blob_length > num_bytes) {
742 0 : tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
743 0 : return;
744 : }
745 :
746 7580 : p = bytes;
747 :
748 : /*
749 : * Note: this points into state->recv_iov!
750 : */
751 7580 : state->out_security_blob = data_blob_const(p, out_security_blob_length);
752 7580 : p += out_security_blob_length;
753 :
754 7580 : status = smb_bytes_pull_str(state, &state->out_native_os,
755 : use_unicode, bytes, num_bytes,
756 : p, &ret);
757 7580 : if (tevent_req_nterror(req, status)) {
758 0 : return;
759 : }
760 7580 : p += ret;
761 :
762 7580 : status = smb_bytes_pull_str(state, &state->out_native_lm,
763 : use_unicode, bytes, num_bytes,
764 : p, &ret);
765 7580 : if (tevent_req_nterror(req, status)) {
766 0 : return;
767 : }
768 : /* p += ret; */
769 :
770 7580 : smb1cli_session_set_id(state->session, state->out_session_id);
771 7580 : smb1cli_session_set_action(state->session, state->out_action);
772 :
773 7580 : tevent_req_done(req);
774 : }
775 :
776 7624 : NTSTATUS smb1cli_session_setup_ext_recv(struct tevent_req *req,
777 : TALLOC_CTX *mem_ctx,
778 : struct iovec **precv_iov,
779 : const uint8_t **precv_inbuf,
780 : DATA_BLOB *out_security_blob,
781 : char **out_native_os,
782 : char **out_native_lm)
783 : {
784 0 : struct smb1cli_session_setup_ext_state *state =
785 7624 : tevent_req_data(req,
786 : struct smb1cli_session_setup_ext_state);
787 0 : NTSTATUS status;
788 7624 : struct iovec *recv_iov = NULL;
789 :
790 7624 : if (tevent_req_is_nterror(req, &status)) {
791 44 : tevent_req_received(req);
792 44 : return status;
793 : }
794 :
795 7580 : recv_iov = talloc_move(mem_ctx, &state->recv_iov);
796 7580 : if (precv_iov != NULL) {
797 7580 : *precv_iov = recv_iov;
798 : }
799 7580 : if (precv_inbuf != NULL) {
800 7580 : *precv_inbuf = state->inbuf;
801 : }
802 :
803 7580 : *out_security_blob = state->out_security_blob;
804 :
805 7580 : if (out_native_os != NULL) {
806 7580 : *out_native_os = talloc_move(mem_ctx, &state->out_native_os);
807 : }
808 :
809 7580 : if (out_native_lm != NULL) {
810 7580 : *out_native_lm = talloc_move(mem_ctx, &state->out_native_lm);
811 : }
812 :
813 : /*
814 : * Return the status from the server:
815 : * NT_STATUS_MORE_PROCESSING_REQUIRED or
816 : * NT_STATUS_OK.
817 : */
818 7580 : status = state->status;
819 7580 : tevent_req_received(req);
820 7580 : return status;
821 : }
|