tstream_npa: Avoid an unnecessary ZERO_STRUCTP
[Samba.git] / libcli / smb / smb1cli_session.c
blob11614df0ae43764d3024290c6567860e878f6aa1
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
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.
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.
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/>.
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"
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;
41 static void smb1cli_session_setup_lm21_done(struct tevent_req *subreq);
43 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)
59 struct tevent_req *req = NULL;
60 struct smb1cli_session_setup_lm21_state *state = NULL;
61 struct tevent_req *subreq = NULL;
62 uint16_t *vwv = NULL;
63 uint8_t *bytes = NULL;
65 req = tevent_req_create(mem_ctx, &state,
66 struct smb1cli_session_setup_lm21_state);
67 if (req == NULL) {
68 return NULL;
70 state->session = session;
71 vwv = state->vwv;
73 if (in_user == NULL) {
74 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
75 return tevent_req_post(req, ev);
78 if (in_domain == NULL) {
79 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
80 return tevent_req_post(req, ev);
83 if (in_apassword.length > UINT16_MAX) {
84 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
85 return tevent_req_post(req, ev);
88 if (in_native_os == NULL && in_native_lm != NULL) {
89 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
90 return tevent_req_post(req, ev);
93 SCVAL(vwv+0, 0, 0xff);
94 SCVAL(vwv+0, 1, 0);
95 SSVAL(vwv+1, 0, 0);
96 SSVAL(vwv+2, 0, in_buf_size);
97 SSVAL(vwv+3, 0, in_mpx_max);
98 SSVAL(vwv+4, 0, in_vc_num);
99 SIVAL(vwv+5, 0, in_sess_key);
100 SSVAL(vwv+7, 0, in_apassword.length);
101 SSVAL(vwv+8, 0, 0); /* reserved */
102 SSVAL(vwv+9, 0, 0); /* reserved */
104 bytes = talloc_array(state, uint8_t,
105 in_apassword.length);
106 if (tevent_req_nomem(bytes, req)) {
107 return tevent_req_post(req, ev);
109 if (in_apassword.length != 0) {
110 memcpy(bytes,
111 in_apassword.data,
112 in_apassword.length);
115 bytes = smb_bytes_push_str(bytes,
116 smbXcli_conn_use_unicode(conn),
117 in_user, strlen(in_user)+1,
118 NULL);
119 bytes = smb_bytes_push_str(bytes,
120 smbXcli_conn_use_unicode(conn),
121 in_domain, strlen(in_domain)+1,
122 NULL);
123 if (in_native_os != NULL) {
124 bytes = smb_bytes_push_str(bytes,
125 smbXcli_conn_use_unicode(conn),
126 in_native_os, strlen(in_native_os)+1,
127 NULL);
129 if (in_native_lm != NULL) {
130 bytes = smb_bytes_push_str(bytes,
131 smbXcli_conn_use_unicode(conn),
132 in_native_lm, strlen(in_native_lm)+1,
133 NULL);
135 if (tevent_req_nomem(bytes, req)) {
136 return tevent_req_post(req, ev);
139 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 talloc_get_size(bytes),
152 bytes);
153 if (tevent_req_nomem(subreq, req)) {
154 return tevent_req_post(req, ev);
156 tevent_req_set_callback(subreq, smb1cli_session_setup_lm21_done, req);
158 return req;
161 static void smb1cli_session_setup_lm21_done(struct tevent_req *subreq)
163 struct tevent_req *req =
164 tevent_req_callback_data(subreq,
165 struct tevent_req);
166 struct smb1cli_session_setup_lm21_state *state =
167 tevent_req_data(req,
168 struct smb1cli_session_setup_lm21_state);
169 NTSTATUS status;
170 uint8_t *inhdr = NULL;
171 uint8_t wct;
172 uint16_t *vwv = NULL;
173 uint32_t num_bytes;
174 uint8_t *bytes = NULL;
175 const uint8_t *p = NULL;
176 size_t ret = 0;
177 uint16_t flags2;
178 bool use_unicode = false;
179 struct smb1cli_req_expected_response expected[] = {
181 .status = NT_STATUS_OK,
182 .wct = 3,
186 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 TALLOC_FREE(subreq);
198 if (tevent_req_nterror(req, status)) {
199 return;
202 flags2 = SVAL(inhdr, HDR_FLG2);
203 if (flags2 & FLAGS2_UNICODE_STRINGS) {
204 use_unicode = true;
207 state->out_session_id = SVAL(inhdr, HDR_UID);
208 state->out_action = SVAL(vwv+2, 0);
210 p = bytes;
212 status = smb_bytes_pull_str(state, &state->out_native_os,
213 use_unicode, bytes, num_bytes,
214 p, &ret);
215 if (tevent_req_nterror(req, status)) {
216 return;
218 p += ret;
220 status = smb_bytes_pull_str(state, &state->out_native_lm,
221 use_unicode, bytes, num_bytes,
222 p, &ret);
223 if (tevent_req_nterror(req, status)) {
224 return;
226 p += ret;
228 smb1cli_session_set_id(state->session, state->out_session_id);
229 smb1cli_session_set_action(state->session, state->out_action);
231 tevent_req_done(req);
234 NTSTATUS smb1cli_session_setup_lm21_recv(struct tevent_req *req,
235 TALLOC_CTX *mem_ctx,
236 char **out_native_os,
237 char **out_native_lm)
239 struct smb1cli_session_setup_lm21_state *state =
240 tevent_req_data(req,
241 struct smb1cli_session_setup_lm21_state);
242 NTSTATUS status;
244 if (tevent_req_is_nterror(req, &status)) {
245 tevent_req_received(req);
246 return status;
249 if (out_native_os != NULL) {
250 *out_native_os = talloc_move(mem_ctx, &state->out_native_os);
253 if (out_native_lm != NULL) {
254 *out_native_lm = talloc_move(mem_ctx, &state->out_native_lm);
257 tevent_req_received(req);
258 return NT_STATUS_OK;
261 struct smb1cli_session_setup_nt1_state {
262 struct smbXcli_session *session;
263 uint16_t vwv[13];
264 struct iovec *recv_iov;
265 uint8_t *inbuf;
266 uint16_t out_session_id;
267 uint16_t out_action;
268 char *out_native_os;
269 char *out_native_lm;
270 char *out_primary_domain;
273 static void smb1cli_session_setup_nt1_done(struct tevent_req *subreq);
275 struct tevent_req *smb1cli_session_setup_nt1_send(TALLOC_CTX *mem_ctx,
276 struct tevent_context *ev,
277 struct smbXcli_conn *conn,
278 uint32_t timeout_msec,
279 uint32_t pid,
280 struct smbXcli_session *session,
281 uint16_t in_buf_size,
282 uint16_t in_mpx_max,
283 uint16_t in_vc_num,
284 uint32_t in_sess_key,
285 const char *in_user,
286 const char *in_domain,
287 const DATA_BLOB in_apassword,
288 const DATA_BLOB in_upassword,
289 uint32_t in_capabilities,
290 const char *in_native_os,
291 const char *in_native_lm)
293 struct tevent_req *req = NULL;
294 struct smb1cli_session_setup_nt1_state *state = NULL;
295 struct tevent_req *subreq = NULL;
296 uint16_t *vwv = NULL;
297 uint8_t *bytes = NULL;
298 size_t align_upassword = 0;
299 size_t apassword_ofs = 0;
300 size_t upassword_ofs = 0;
302 req = tevent_req_create(mem_ctx, &state,
303 struct smb1cli_session_setup_nt1_state);
304 if (req == NULL) {
305 return NULL;
307 state->session = session;
308 vwv = state->vwv;
310 if (in_user == NULL) {
311 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
312 return tevent_req_post(req, ev);
315 if (in_domain == NULL) {
316 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
317 return tevent_req_post(req, ev);
320 if (in_apassword.length > UINT16_MAX) {
321 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
322 return tevent_req_post(req, ev);
325 if (in_upassword.length > UINT16_MAX) {
326 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
327 return tevent_req_post(req, ev);
330 if (in_native_os == NULL && in_native_lm != NULL) {
331 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
332 return tevent_req_post(req, ev);
335 SCVAL(vwv+0, 0, 0xff);
336 SCVAL(vwv+0, 1, 0);
337 SSVAL(vwv+1, 0, 0);
338 SSVAL(vwv+2, 0, in_buf_size);
339 SSVAL(vwv+3, 0, in_mpx_max);
340 SSVAL(vwv+4, 0, in_vc_num);
341 SIVAL(vwv+5, 0, in_sess_key);
342 SSVAL(vwv+7, 0, in_apassword.length);
343 SSVAL(vwv+8, 0, in_upassword.length);
344 SSVAL(vwv+9, 0, 0); /* reserved */
345 SSVAL(vwv+10, 0, 0); /* reserved */
346 SIVAL(vwv+11, 0, in_capabilities);
348 if (in_apassword.length == 0 && in_upassword.length > 0) {
350 * This is plaintext auth with a unicode password,
351 * we need to align the buffer.
353 * This is what smbclient and Windows XP send as
354 * a client. And what smbd expects.
356 * But it doesn't follow [MS-CIFS] (v20160714)
357 * 2.2.4.53.1 SMB_COM_SESSION_SETUP_ANDX Request:
359 * ...
361 * If SMB_FLAGS2_UNICODE is set (1), the value of OEMPasswordLen
362 * MUST be 0x0000 and the password MUST be encoded using
363 * UTF-16LE Unicode. Padding MUST NOT be added to
364 * align this plaintext Unicode string to a word boundary.
366 * ...
368 uint16_t security_mode = smb1cli_conn_server_security_mode(conn);
370 if (!(security_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)) {
371 align_upassword = 1;
375 bytes = talloc_array(state, uint8_t,
376 in_apassword.length +
377 align_upassword +
378 in_upassword.length);
379 if (tevent_req_nomem(bytes, req)) {
380 return tevent_req_post(req, ev);
382 if (in_apassword.length != 0) {
383 memcpy(bytes + apassword_ofs,
384 in_apassword.data,
385 in_apassword.length);
386 upassword_ofs += in_apassword.length;
388 if (align_upassword != 0) {
389 memset(bytes + upassword_ofs, 0, align_upassword);
390 upassword_ofs += align_upassword;
392 if (in_upassword.length != 0) {
393 memcpy(bytes + upassword_ofs,
394 in_upassword.data,
395 in_upassword.length);
398 bytes = smb_bytes_push_str(bytes,
399 smbXcli_conn_use_unicode(conn),
400 in_user, strlen(in_user)+1,
401 NULL);
402 bytes = smb_bytes_push_str(bytes,
403 smbXcli_conn_use_unicode(conn),
404 in_domain, strlen(in_domain)+1,
405 NULL);
406 if (in_native_os != NULL) {
407 bytes = smb_bytes_push_str(bytes,
408 smbXcli_conn_use_unicode(conn),
409 in_native_os, strlen(in_native_os)+1,
410 NULL);
412 if (in_native_lm != NULL) {
413 bytes = smb_bytes_push_str(bytes,
414 smbXcli_conn_use_unicode(conn),
415 in_native_lm, strlen(in_native_lm)+1,
416 NULL);
418 if (tevent_req_nomem(bytes, req)) {
419 return tevent_req_post(req, ev);
422 subreq = smb1cli_req_send(state, ev, conn,
423 SMBsesssetupX,
424 0, /* additional_flags */
425 0, /* clear_flags */
426 0, /* additional_flags2 */
427 0, /* clear_flags2 */
428 timeout_msec,
429 pid,
430 NULL, /* tcon */
431 session,
432 13, /* wct */
433 vwv,
434 talloc_get_size(bytes),
435 bytes);
436 if (tevent_req_nomem(subreq, req)) {
437 return tevent_req_post(req, ev);
439 tevent_req_set_callback(subreq, smb1cli_session_setup_nt1_done, req);
441 return req;
444 static void smb1cli_session_setup_nt1_done(struct tevent_req *subreq)
446 struct tevent_req *req =
447 tevent_req_callback_data(subreq,
448 struct tevent_req);
449 struct smb1cli_session_setup_nt1_state *state =
450 tevent_req_data(req,
451 struct smb1cli_session_setup_nt1_state);
452 NTSTATUS status;
453 uint8_t *inhdr = NULL;
454 uint8_t wct;
455 uint16_t *vwv = NULL;
456 uint32_t num_bytes;
457 uint8_t *bytes = NULL;
458 const uint8_t *p = NULL;
459 size_t ret = 0;
460 uint16_t flags2;
461 bool use_unicode = false;
462 struct smb1cli_req_expected_response expected[] = {
464 .status = NT_STATUS_OK,
465 .wct = 3,
469 status = smb1cli_req_recv(subreq, state,
470 &state->recv_iov,
471 &inhdr,
472 &wct,
473 &vwv,
474 NULL, /* pvwv_offset */
475 &num_bytes,
476 &bytes,
477 NULL, /* pbytes_offset */
478 &state->inbuf,
479 expected, ARRAY_SIZE(expected));
480 TALLOC_FREE(subreq);
481 if (tevent_req_nterror(req, status)) {
482 return;
485 flags2 = SVAL(inhdr, HDR_FLG2);
486 if (flags2 & FLAGS2_UNICODE_STRINGS) {
487 use_unicode = true;
490 state->out_session_id = SVAL(inhdr, HDR_UID);
491 state->out_action = SVAL(vwv+2, 0);
493 p = bytes;
495 status = smb_bytes_pull_str(state, &state->out_native_os,
496 use_unicode, bytes, num_bytes,
497 p, &ret);
498 if (tevent_req_nterror(req, status)) {
499 return;
501 p += ret;
503 status = smb_bytes_pull_str(state, &state->out_native_lm,
504 use_unicode, bytes, num_bytes,
505 p, &ret);
506 if (tevent_req_nterror(req, status)) {
507 return;
509 p += ret;
511 status = smb_bytes_pull_str(state, &state->out_primary_domain,
512 use_unicode, bytes, num_bytes,
513 p, &ret);
514 if (tevent_req_nterror(req, status)) {
515 return;
517 p += ret;
519 smb1cli_session_set_id(state->session, state->out_session_id);
520 smb1cli_session_set_action(state->session, state->out_action);
522 tevent_req_done(req);
525 NTSTATUS smb1cli_session_setup_nt1_recv(struct tevent_req *req,
526 TALLOC_CTX *mem_ctx,
527 struct iovec **precv_iov,
528 const uint8_t **precv_inbuf,
529 char **out_native_os,
530 char **out_native_lm,
531 char **out_primary_domain)
533 struct smb1cli_session_setup_nt1_state *state =
534 tevent_req_data(req,
535 struct smb1cli_session_setup_nt1_state);
536 NTSTATUS status;
537 struct iovec *recv_iov = NULL;
539 if (tevent_req_is_nterror(req, &status)) {
540 tevent_req_received(req);
541 return status;
544 recv_iov = talloc_move(mem_ctx, &state->recv_iov);
545 if (precv_iov != NULL) {
546 *precv_iov = recv_iov;
548 if (precv_inbuf != NULL) {
549 *precv_inbuf = state->inbuf;
552 if (out_native_os != NULL) {
553 *out_native_os = talloc_move(mem_ctx, &state->out_native_os);
556 if (out_native_lm != NULL) {
557 *out_native_lm = talloc_move(mem_ctx, &state->out_native_lm);
560 if (out_primary_domain != NULL) {
561 *out_primary_domain = talloc_move(mem_ctx,
562 &state->out_primary_domain);
565 tevent_req_received(req);
566 return NT_STATUS_OK;
569 struct smb1cli_session_setup_ext_state {
570 struct smbXcli_session *session;
571 uint16_t vwv[12];
572 struct iovec *recv_iov;
573 uint8_t *inbuf;
574 NTSTATUS status;
575 uint16_t out_session_id;
576 uint16_t out_action;
577 DATA_BLOB out_security_blob;
578 char *out_native_os;
579 char *out_native_lm;
582 static void smb1cli_session_setup_ext_done(struct tevent_req *subreq);
584 struct tevent_req *smb1cli_session_setup_ext_send(TALLOC_CTX *mem_ctx,
585 struct tevent_context *ev,
586 struct smbXcli_conn *conn,
587 uint32_t timeout_msec,
588 uint32_t pid,
589 struct smbXcli_session *session,
590 uint16_t in_buf_size,
591 uint16_t in_mpx_max,
592 uint16_t in_vc_num,
593 uint32_t in_sess_key,
594 const DATA_BLOB in_security_blob,
595 uint32_t in_capabilities,
596 const char *in_native_os,
597 const char *in_native_lm)
599 struct tevent_req *req = NULL;
600 struct smb1cli_session_setup_ext_state *state = NULL;
601 struct tevent_req *subreq = NULL;
602 uint16_t *vwv = NULL;
603 uint8_t *bytes = NULL;
605 req = tevent_req_create(mem_ctx, &state,
606 struct smb1cli_session_setup_ext_state);
607 if (req == NULL) {
608 return NULL;
610 state->session = session;
611 vwv = state->vwv;
613 if (in_security_blob.length > UINT16_MAX) {
614 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
615 return tevent_req_post(req, ev);
618 if (in_native_os == NULL && in_native_lm != NULL) {
619 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
620 return tevent_req_post(req, ev);
623 SCVAL(vwv+0, 0, 0xff);
624 SCVAL(vwv+0, 1, 0);
625 SSVAL(vwv+1, 0, 0);
626 SSVAL(vwv+2, 0, in_buf_size);
627 SSVAL(vwv+3, 0, in_mpx_max);
628 SSVAL(vwv+4, 0, in_vc_num);
629 SIVAL(vwv+5, 0, in_sess_key);
630 SSVAL(vwv+7, 0, in_security_blob.length);
631 SSVAL(vwv+8, 0, 0); /* reserved */
632 SSVAL(vwv+9, 0, 0); /* reserved */
633 SIVAL(vwv+10, 0, in_capabilities);
635 bytes = talloc_array(state, uint8_t,
636 in_security_blob.length);
637 if (tevent_req_nomem(bytes, req)) {
638 return tevent_req_post(req, ev);
640 if (in_security_blob.length != 0) {
641 memcpy(bytes,
642 in_security_blob.data,
643 in_security_blob.length);
646 if (in_native_os != NULL) {
647 bytes = smb_bytes_push_str(bytes,
648 smbXcli_conn_use_unicode(conn),
649 in_native_os, strlen(in_native_os)+1,
650 NULL);
652 if (in_native_lm != NULL) {
653 bytes = smb_bytes_push_str(bytes,
654 smbXcli_conn_use_unicode(conn),
655 in_native_lm, strlen(in_native_lm)+1,
656 NULL);
658 if (tevent_req_nomem(bytes, req)) {
659 return tevent_req_post(req, ev);
662 subreq = smb1cli_req_send(state, ev, conn,
663 SMBsesssetupX,
664 0, /* additional_flags */
665 0, /* clear_flags */
666 0, /* additional_flags2 */
667 0, /* clear_flags2 */
668 timeout_msec,
669 pid,
670 NULL, /* tcon */
671 session,
672 12, /* wct */
673 vwv,
674 talloc_get_size(bytes),
675 bytes);
676 if (tevent_req_nomem(subreq, req)) {
677 return tevent_req_post(req, ev);
679 tevent_req_set_callback(subreq, smb1cli_session_setup_ext_done, req);
681 return req;
684 static void smb1cli_session_setup_ext_done(struct tevent_req *subreq)
686 struct tevent_req *req =
687 tevent_req_callback_data(subreq,
688 struct tevent_req);
689 struct smb1cli_session_setup_ext_state *state =
690 tevent_req_data(req,
691 struct smb1cli_session_setup_ext_state);
692 NTSTATUS status;
693 uint8_t *inhdr = NULL;
694 uint8_t wct;
695 uint16_t *vwv = NULL;
696 uint32_t num_bytes;
697 uint8_t *bytes = NULL;
698 const uint8_t *p = NULL;
699 size_t ret = 0;
700 uint16_t flags2;
701 uint16_t out_security_blob_length = 0;
702 bool use_unicode = false;
703 struct smb1cli_req_expected_response expected[] = {
705 .status = NT_STATUS_OK,
706 .wct = 4,
709 .status = NT_STATUS_MORE_PROCESSING_REQUIRED,
710 .wct = 4,
714 status = smb1cli_req_recv(subreq, state,
715 &state->recv_iov,
716 &inhdr,
717 &wct,
718 &vwv,
719 NULL, /* pvwv_offset */
720 &num_bytes,
721 &bytes,
722 NULL, /* pbytes_offset */
723 &state->inbuf,
724 expected, ARRAY_SIZE(expected));
725 TALLOC_FREE(subreq);
726 state->status = status;
727 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
728 status = NT_STATUS_OK;
730 if (tevent_req_nterror(req, status)) {
731 return;
734 flags2 = SVAL(inhdr, HDR_FLG2);
735 if (flags2 & FLAGS2_UNICODE_STRINGS) {
736 use_unicode = true;
739 state->out_session_id = SVAL(inhdr, HDR_UID);
740 state->out_action = SVAL(vwv+2, 0);
741 out_security_blob_length = SVAL(vwv+3, 0);
743 if (out_security_blob_length > num_bytes) {
744 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
745 return;
748 p = bytes;
751 * Note: this points into state->recv_iov!
753 state->out_security_blob = data_blob_const(p, out_security_blob_length);
754 p += out_security_blob_length;
756 status = smb_bytes_pull_str(state, &state->out_native_os,
757 use_unicode, bytes, num_bytes,
758 p, &ret);
759 if (tevent_req_nterror(req, status)) {
760 return;
762 p += ret;
764 status = smb_bytes_pull_str(state, &state->out_native_lm,
765 use_unicode, bytes, num_bytes,
766 p, &ret);
767 if (tevent_req_nterror(req, status)) {
768 return;
770 /* p += ret; */
772 smb1cli_session_set_id(state->session, state->out_session_id);
773 smb1cli_session_set_action(state->session, state->out_action);
775 tevent_req_done(req);
778 NTSTATUS smb1cli_session_setup_ext_recv(struct tevent_req *req,
779 TALLOC_CTX *mem_ctx,
780 struct iovec **precv_iov,
781 const uint8_t **precv_inbuf,
782 DATA_BLOB *out_security_blob,
783 char **out_native_os,
784 char **out_native_lm)
786 struct smb1cli_session_setup_ext_state *state =
787 tevent_req_data(req,
788 struct smb1cli_session_setup_ext_state);
789 NTSTATUS status;
790 struct iovec *recv_iov = NULL;
792 if (tevent_req_is_nterror(req, &status)) {
793 tevent_req_received(req);
794 return status;
797 recv_iov = talloc_move(mem_ctx, &state->recv_iov);
798 if (precv_iov != NULL) {
799 *precv_iov = recv_iov;
801 if (precv_inbuf != NULL) {
802 *precv_inbuf = state->inbuf;
805 *out_security_blob = state->out_security_blob;
807 if (out_native_os != NULL) {
808 *out_native_os = talloc_move(mem_ctx, &state->out_native_os);
811 if (out_native_lm != NULL) {
812 *out_native_lm = talloc_move(mem_ctx, &state->out_native_lm);
816 * Return the status from the server:
817 * NT_STATUS_MORE_PROCESSING_REQUIRED or
818 * NT_STATUS_OK.
820 status = state->status;
821 tevent_req_received(req);
822 return status;