Coverage Report

Created: 2026-06-07 07:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/libcli/smb/smb1cli_session.c
Line
Count
Source
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
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
0
{
59
0
  struct tevent_req *req = NULL;
60
0
  struct smb1cli_session_setup_lm21_state *state = NULL;
61
0
  struct tevent_req *subreq = NULL;
62
0
  uint16_t *vwv = NULL;
63
0
  uint8_t *bytes = NULL;
64
65
0
  req = tevent_req_create(mem_ctx, &state,
66
0
        struct smb1cli_session_setup_lm21_state);
67
0
  if (req == NULL) {
68
0
    return NULL;
69
0
  }
70
0
  state->session = session;
71
0
  vwv = state->vwv;
72
73
0
  if (in_user == NULL) {
74
0
    tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
75
0
    return tevent_req_post(req, ev);
76
0
  }
77
78
0
  if (in_domain == NULL) {
79
0
    tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
80
0
    return tevent_req_post(req, ev);
81
0
  }
82
83
0
  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
0
  }
87
88
0
  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
0
  }
92
93
0
  SCVAL(vwv+0, 0, 0xff);
94
0
  SCVAL(vwv+0, 1, 0);
95
0
  SSVAL(vwv+1, 0, 0);
96
0
  SSVAL(vwv+2, 0, in_buf_size);
97
0
  SSVAL(vwv+3, 0, in_mpx_max);
98
0
  SSVAL(vwv+4, 0, in_vc_num);
99
0
  SIVAL(vwv+5, 0, in_sess_key);
100
0
  SSVAL(vwv+7, 0, in_apassword.length);
101
0
  SSVAL(vwv+8, 0, 0); /* reserved */
102
0
  SSVAL(vwv+9, 0, 0); /* reserved */
103
104
0
  bytes = talloc_array(state, uint8_t,
105
0
           in_apassword.length);
106
0
  if (tevent_req_nomem(bytes, req)) {
107
0
    return tevent_req_post(req, ev);
108
0
  }
109
0
  if (in_apassword.length != 0) {
110
0
    memcpy(bytes,
111
0
           in_apassword.data,
112
0
           in_apassword.length);
113
0
  }
114
115
0
  bytes = smb_bytes_push_str(bytes,
116
0
           smbXcli_conn_use_unicode(conn),
117
0
           in_user, strlen(in_user)+1,
118
0
           NULL);
119
0
  bytes = smb_bytes_push_str(bytes,
120
0
           smbXcli_conn_use_unicode(conn),
121
0
           in_domain, strlen(in_domain)+1,
122
0
           NULL);
123
0
  if (in_native_os != NULL) {
124
0
    bytes = smb_bytes_push_str(bytes,
125
0
             smbXcli_conn_use_unicode(conn),
126
0
             in_native_os, strlen(in_native_os)+1,
127
0
             NULL);
128
0
  }
129
0
  if (in_native_lm != NULL) {
130
0
    bytes = smb_bytes_push_str(bytes,
131
0
             smbXcli_conn_use_unicode(conn),
132
0
             in_native_lm, strlen(in_native_lm)+1,
133
0
             NULL);
134
0
  }
135
0
  if (tevent_req_nomem(bytes, req)) {
136
0
    return tevent_req_post(req, ev);
137
0
  }
138
139
0
  subreq = smb1cli_req_send(state, ev, conn,
140
0
          SMBsesssetupX,
141
0
          0, /*  additional_flags */
142
0
          0, /*  clear_flags */
143
0
          0, /*  additional_flags2 */
144
0
          0, /*  clear_flags2 */
145
0
          timeout_msec,
146
0
          pid,
147
0
          NULL, /* tcon */
148
0
          session,
149
0
          10, /* wct */
150
0
          vwv,
151
0
          talloc_get_size(bytes),
152
0
          bytes);
153
0
  if (tevent_req_nomem(subreq, req)) {
154
0
    return tevent_req_post(req, ev);
155
0
  }
156
0
  tevent_req_set_callback(subreq, smb1cli_session_setup_lm21_done, req);
157
158
0
  return req;
159
0
}
160
161
static void smb1cli_session_setup_lm21_done(struct tevent_req *subreq)
162
0
{
163
0
  struct tevent_req *req =
164
0
    tevent_req_callback_data(subreq,
165
0
    struct tevent_req);
166
0
  struct smb1cli_session_setup_lm21_state *state =
167
0
    tevent_req_data(req,
168
0
    struct smb1cli_session_setup_lm21_state);
169
0
  NTSTATUS status;
170
0
  uint8_t *inhdr = NULL;
171
0
  uint8_t wct;
172
0
  uint16_t *vwv = NULL;
173
0
  uint32_t num_bytes;
174
0
  uint8_t *bytes = NULL;
175
0
  const uint8_t *p = NULL;
176
0
  size_t ret = 0;
177
0
  uint16_t flags2;
178
0
  bool use_unicode = false;
179
0
  struct smb1cli_req_expected_response expected[] = {
180
0
  {
181
0
    .status = NT_STATUS_OK,
182
0
    .wct    = 3,
183
0
  },
184
0
  };
185
186
0
  status = smb1cli_req_recv(subreq, state,
187
0
          &state->recv_iov,
188
0
          &inhdr,
189
0
          &wct,
190
0
          &vwv,
191
0
          NULL, /* pvwv_offset */
192
0
          &num_bytes,
193
0
          &bytes,
194
0
          NULL, /* pbytes_offset */
195
0
          NULL, /* pinbuf */
196
0
          expected, ARRAY_SIZE(expected));
197
0
  TALLOC_FREE(subreq);
198
0
  if (tevent_req_nterror(req, status)) {
199
0
    return;
200
0
  }
201
202
0
  flags2 = SVAL(inhdr, HDR_FLG2);
203
0
  if (flags2 & FLAGS2_UNICODE_STRINGS) {
204
0
    use_unicode = true;
205
0
  }
206
207
0
  state->out_session_id = SVAL(inhdr, HDR_UID);
208
0
  state->out_action = SVAL(vwv+2, 0);
209
210
0
  p = bytes;
211
212
0
  status = smb_bytes_pull_str(state, &state->out_native_os,
213
0
            use_unicode, bytes, num_bytes,
214
0
            p, &ret);
215
0
  if (tevent_req_nterror(req, status)) {
216
0
    return;
217
0
  }
218
0
  p += ret;
219
220
0
  status = smb_bytes_pull_str(state, &state->out_native_lm,
221
0
            use_unicode, bytes, num_bytes,
222
0
            p, &ret);
223
0
  if (tevent_req_nterror(req, status)) {
224
0
    return;
225
0
  }
226
227
0
  smb1cli_session_set_id(state->session, state->out_session_id);
228
0
  smb1cli_session_set_action(state->session, state->out_action);
229
230
0
  tevent_req_done(req);
231
0
}
232
233
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
0
{
238
0
  struct smb1cli_session_setup_lm21_state *state =
239
0
    tevent_req_data(req,
240
0
    struct smb1cli_session_setup_lm21_state);
241
0
  NTSTATUS status;
242
243
0
  if (tevent_req_is_nterror(req, &status)) {
244
0
    tevent_req_received(req);
245
0
    return status;
246
0
  }
247
248
0
  if (out_native_os != NULL) {
249
0
    *out_native_os = talloc_move(mem_ctx, &state->out_native_os);
250
0
  }
251
252
0
  if (out_native_lm != NULL) {
253
0
    *out_native_lm = talloc_move(mem_ctx, &state->out_native_lm);
254
0
  }
255
256
0
  tevent_req_received(req);
257
0
  return NT_STATUS_OK;
258
0
}
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
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
0
{
292
0
  struct tevent_req *req = NULL;
293
0
  struct smb1cli_session_setup_nt1_state *state = NULL;
294
0
  struct tevent_req *subreq = NULL;
295
0
  uint16_t *vwv = NULL;
296
0
  uint8_t *bytes = NULL;
297
0
  size_t align_upassword = 0;
298
0
  size_t apassword_ofs = 0;
299
0
  size_t upassword_ofs = 0;
300
301
0
  req = tevent_req_create(mem_ctx, &state,
302
0
        struct smb1cli_session_setup_nt1_state);
303
0
  if (req == NULL) {
304
0
    return NULL;
305
0
  }
306
0
  state->session = session;
307
0
  vwv = state->vwv;
308
309
0
  if (in_user == NULL) {
310
0
    tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
311
0
    return tevent_req_post(req, ev);
312
0
  }
313
314
0
  if (in_domain == NULL) {
315
0
    tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
316
0
    return tevent_req_post(req, ev);
317
0
  }
318
319
0
  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
0
  }
323
324
0
  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
0
  }
328
329
0
  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
0
  }
333
334
0
  SCVAL(vwv+0,  0, 0xff);
335
0
  SCVAL(vwv+0,  1, 0);
336
0
  SSVAL(vwv+1,  0, 0);
337
0
  SSVAL(vwv+2,  0, in_buf_size);
338
0
  SSVAL(vwv+3,  0, in_mpx_max);
339
0
  SSVAL(vwv+4,  0, in_vc_num);
340
0
  SIVAL(vwv+5,  0, in_sess_key);
341
0
  SSVAL(vwv+7,  0, in_apassword.length);
342
0
  SSVAL(vwv+8,  0, in_upassword.length);
343
0
  SSVAL(vwv+9,  0, 0); /* reserved */
344
0
  SSVAL(vwv+10, 0, 0); /* reserved */
345
0
  SIVAL(vwv+11, 0, in_capabilities);
346
347
0
  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
0
    }
372
0
  }
373
374
0
  bytes = talloc_array(state, uint8_t,
375
0
           in_apassword.length +
376
0
           align_upassword +
377
0
           in_upassword.length);
378
0
  if (tevent_req_nomem(bytes, req)) {
379
0
    return tevent_req_post(req, ev);
380
0
  }
381
0
  if (in_apassword.length != 0) {
382
0
    memcpy(bytes + apassword_ofs,
383
0
           in_apassword.data,
384
0
           in_apassword.length);
385
0
    upassword_ofs += in_apassword.length;
386
0
  }
387
0
  if (align_upassword != 0) {
388
0
    memset(bytes + upassword_ofs, 0, align_upassword);
389
0
    upassword_ofs += align_upassword;
390
0
  }
391
0
  if (in_upassword.length != 0) {
392
0
    memcpy(bytes + upassword_ofs,
393
0
           in_upassword.data,
394
0
           in_upassword.length);
395
0
  }
396
397
0
  bytes = smb_bytes_push_str(bytes,
398
0
           smbXcli_conn_use_unicode(conn),
399
0
           in_user, strlen(in_user)+1,
400
0
           NULL);
401
0
  bytes = smb_bytes_push_str(bytes,
402
0
           smbXcli_conn_use_unicode(conn),
403
0
           in_domain, strlen(in_domain)+1,
404
0
           NULL);
405
0
  if (in_native_os != NULL) {
406
0
    bytes = smb_bytes_push_str(bytes,
407
0
             smbXcli_conn_use_unicode(conn),
408
0
             in_native_os, strlen(in_native_os)+1,
409
0
             NULL);
410
0
  }
411
0
  if (in_native_lm != NULL) {
412
0
    bytes = smb_bytes_push_str(bytes,
413
0
             smbXcli_conn_use_unicode(conn),
414
0
             in_native_lm, strlen(in_native_lm)+1,
415
0
             NULL);
416
0
  }
417
0
  if (tevent_req_nomem(bytes, req)) {
418
0
    return tevent_req_post(req, ev);
419
0
  }
420
421
0
  subreq = smb1cli_req_send(state, ev, conn,
422
0
          SMBsesssetupX,
423
0
          0, /*  additional_flags */
424
0
          0, /*  clear_flags */
425
0
          0, /*  additional_flags2 */
426
0
          0, /*  clear_flags2 */
427
0
          timeout_msec,
428
0
          pid,
429
0
          NULL, /* tcon */
430
0
          session,
431
0
          13, /* wct */
432
0
          vwv,
433
0
          talloc_get_size(bytes),
434
0
          bytes);
435
0
  if (tevent_req_nomem(subreq, req)) {
436
0
    return tevent_req_post(req, ev);
437
0
  }
438
0
  tevent_req_set_callback(subreq, smb1cli_session_setup_nt1_done, req);
439
440
0
  return req;
441
0
}
442
443
static void smb1cli_session_setup_nt1_done(struct tevent_req *subreq)
444
0
{
445
0
  struct tevent_req *req =
446
0
    tevent_req_callback_data(subreq,
447
0
    struct tevent_req);
448
0
  struct smb1cli_session_setup_nt1_state *state =
449
0
    tevent_req_data(req,
450
0
    struct smb1cli_session_setup_nt1_state);
451
0
  NTSTATUS status;
452
0
  uint8_t *inhdr = NULL;
453
0
  uint8_t wct;
454
0
  uint16_t *vwv = NULL;
455
0
  uint32_t num_bytes;
456
0
  uint8_t *bytes = NULL;
457
0
  const uint8_t *p = NULL;
458
0
  size_t ret = 0;
459
0
  uint16_t flags2;
460
0
  bool use_unicode = false;
461
0
  struct smb1cli_req_expected_response expected[] = {
462
0
  {
463
0
    .status = NT_STATUS_OK,
464
0
    .wct    = 3,
465
0
  },
466
0
  };
467
468
0
  status = smb1cli_req_recv(subreq, state,
469
0
          &state->recv_iov,
470
0
          &inhdr,
471
0
          &wct,
472
0
          &vwv,
473
0
          NULL, /* pvwv_offset */
474
0
          &num_bytes,
475
0
          &bytes,
476
0
          NULL, /* pbytes_offset */
477
0
          &state->inbuf,
478
0
          expected, ARRAY_SIZE(expected));
479
0
  TALLOC_FREE(subreq);
480
0
  if (tevent_req_nterror(req, status)) {
481
0
    return;
482
0
  }
483
484
0
  flags2 = SVAL(inhdr, HDR_FLG2);
485
0
  if (flags2 & FLAGS2_UNICODE_STRINGS) {
486
0
    use_unicode = true;
487
0
  }
488
489
0
  state->out_session_id = SVAL(inhdr, HDR_UID);
490
0
  state->out_action = SVAL(vwv+2, 0);
491
492
0
  p = bytes;
493
494
0
  status = smb_bytes_pull_str(state, &state->out_native_os,
495
0
            use_unicode, bytes, num_bytes,
496
0
            p, &ret);
497
0
  if (tevent_req_nterror(req, status)) {
498
0
    return;
499
0
  }
500
0
  p += ret;
501
502
0
  status = smb_bytes_pull_str(state, &state->out_native_lm,
503
0
            use_unicode, bytes, num_bytes,
504
0
            p, &ret);
505
0
  if (tevent_req_nterror(req, status)) {
506
0
    return;
507
0
  }
508
0
  p += ret;
509
510
0
  status = smb_bytes_pull_str(state, &state->out_primary_domain,
511
0
            use_unicode, bytes, num_bytes,
512
0
            p, &ret);
513
0
  if (tevent_req_nterror(req, status)) {
514
0
    return;
515
0
  }
516
517
0
  smb1cli_session_set_id(state->session, state->out_session_id);
518
0
  smb1cli_session_set_action(state->session, state->out_action);
519
520
0
  tevent_req_done(req);
521
0
}
522
523
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
0
{
531
0
  struct smb1cli_session_setup_nt1_state *state =
532
0
    tevent_req_data(req,
533
0
    struct smb1cli_session_setup_nt1_state);
534
0
  NTSTATUS status;
535
0
  struct iovec *recv_iov = NULL;
536
537
0
  if (tevent_req_is_nterror(req, &status)) {
538
0
    tevent_req_received(req);
539
0
    return status;
540
0
  }
541
542
0
  recv_iov = talloc_move(mem_ctx, &state->recv_iov);
543
0
  if (precv_iov != NULL) {
544
0
    *precv_iov = recv_iov;
545
0
  }
546
0
  if (precv_inbuf != NULL) {
547
0
    *precv_inbuf = state->inbuf;
548
0
  }
549
550
0
  if (out_native_os != NULL) {
551
0
    *out_native_os = talloc_move(mem_ctx, &state->out_native_os);
552
0
  }
553
554
0
  if (out_native_lm != NULL) {
555
0
    *out_native_lm = talloc_move(mem_ctx, &state->out_native_lm);
556
0
  }
557
558
0
  if (out_primary_domain != NULL) {
559
0
    *out_primary_domain = talloc_move(mem_ctx,
560
0
              &state->out_primary_domain);
561
0
  }
562
563
0
  tevent_req_received(req);
564
0
  return NT_STATUS_OK;
565
0
}
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
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
0
{
597
0
  struct tevent_req *req = NULL;
598
0
  struct smb1cli_session_setup_ext_state *state = NULL;
599
0
  struct tevent_req *subreq = NULL;
600
0
  uint16_t *vwv = NULL;
601
0
  uint8_t *bytes = NULL;
602
603
0
  req = tevent_req_create(mem_ctx, &state,
604
0
        struct smb1cli_session_setup_ext_state);
605
0
  if (req == NULL) {
606
0
    return NULL;
607
0
  }
608
0
  state->session = session;
609
0
  vwv = state->vwv;
610
611
0
  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
0
  }
615
616
0
  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
0
  }
620
621
0
  SCVAL(vwv+0,  0, 0xff);
622
0
  SCVAL(vwv+0,  1, 0);
623
0
  SSVAL(vwv+1,  0, 0);
624
0
  SSVAL(vwv+2,  0, in_buf_size);
625
0
  SSVAL(vwv+3,  0, in_mpx_max);
626
0
  SSVAL(vwv+4,  0, in_vc_num);
627
0
  SIVAL(vwv+5,  0, in_sess_key);
628
0
  SSVAL(vwv+7,  0, in_security_blob.length);
629
0
  SSVAL(vwv+8,  0, 0); /* reserved */
630
0
  SSVAL(vwv+9,  0, 0); /* reserved */
631
0
  SIVAL(vwv+10, 0, in_capabilities);
632
633
0
  bytes = talloc_array(state, uint8_t,
634
0
           in_security_blob.length);
635
0
  if (tevent_req_nomem(bytes, req)) {
636
0
    return tevent_req_post(req, ev);
637
0
  }
638
0
  if (in_security_blob.length != 0) {
639
0
    memcpy(bytes,
640
0
           in_security_blob.data,
641
0
           in_security_blob.length);
642
0
  }
643
644
0
  if (in_native_os != NULL) {
645
0
    bytes = smb_bytes_push_str(bytes,
646
0
             smbXcli_conn_use_unicode(conn),
647
0
             in_native_os, strlen(in_native_os)+1,
648
0
             NULL);
649
0
  }
650
0
  if (in_native_lm != NULL) {
651
0
    bytes = smb_bytes_push_str(bytes,
652
0
             smbXcli_conn_use_unicode(conn),
653
0
             in_native_lm, strlen(in_native_lm)+1,
654
0
             NULL);
655
0
  }
656
0
  if (tevent_req_nomem(bytes, req)) {
657
0
    return tevent_req_post(req, ev);
658
0
  }
659
660
0
  subreq = smb1cli_req_send(state, ev, conn,
661
0
          SMBsesssetupX,
662
0
          0, /*  additional_flags */
663
0
          0, /*  clear_flags */
664
0
          0, /*  additional_flags2 */
665
0
          0, /*  clear_flags2 */
666
0
          timeout_msec,
667
0
          pid,
668
0
          NULL, /* tcon */
669
0
          session,
670
0
          12, /* wct */
671
0
          vwv,
672
0
          talloc_get_size(bytes),
673
0
          bytes);
674
0
  if (tevent_req_nomem(subreq, req)) {
675
0
    return tevent_req_post(req, ev);
676
0
  }
677
0
  tevent_req_set_callback(subreq, smb1cli_session_setup_ext_done, req);
678
679
0
  return req;
680
0
}
681
682
static void smb1cli_session_setup_ext_done(struct tevent_req *subreq)
683
0
{
684
0
  struct tevent_req *req =
685
0
    tevent_req_callback_data(subreq,
686
0
    struct tevent_req);
687
0
  struct smb1cli_session_setup_ext_state *state =
688
0
    tevent_req_data(req,
689
0
    struct smb1cli_session_setup_ext_state);
690
0
  NTSTATUS status;
691
0
  uint8_t *inhdr = NULL;
692
0
  uint8_t wct;
693
0
  uint16_t *vwv = NULL;
694
0
  uint32_t num_bytes;
695
0
  uint8_t *bytes = NULL;
696
0
  const uint8_t *p = NULL;
697
0
  size_t ret = 0;
698
0
  uint16_t flags2;
699
0
  uint16_t out_security_blob_length = 0;
700
0
  bool use_unicode = false;
701
0
  struct smb1cli_req_expected_response expected[] = {
702
0
  {
703
0
    .status = NT_STATUS_OK,
704
0
    .wct    = 4,
705
0
  },
706
0
  {
707
0
    .status = NT_STATUS_MORE_PROCESSING_REQUIRED,
708
0
    .wct    = 4,
709
0
  },
710
0
  };
711
712
0
  status = smb1cli_req_recv(subreq, state,
713
0
          &state->recv_iov,
714
0
          &inhdr,
715
0
          &wct,
716
0
          &vwv,
717
0
          NULL, /* pvwv_offset */
718
0
          &num_bytes,
719
0
          &bytes,
720
0
          NULL, /* pbytes_offset */
721
0
          &state->inbuf,
722
0
          expected, ARRAY_SIZE(expected));
723
0
  TALLOC_FREE(subreq);
724
0
  state->status = status;
725
0
  if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
726
0
    status = NT_STATUS_OK;
727
0
  }
728
0
  if (tevent_req_nterror(req, status)) {
729
0
    return;
730
0
  }
731
732
0
  flags2 = SVAL(inhdr, HDR_FLG2);
733
0
  if (flags2 & FLAGS2_UNICODE_STRINGS) {
734
0
    use_unicode = true;
735
0
  }
736
737
0
  state->out_session_id = SVAL(inhdr, HDR_UID);
738
0
  state->out_action = SVAL(vwv+2, 0);
739
0
  out_security_blob_length = SVAL(vwv+3, 0);
740
741
0
  if (out_security_blob_length > num_bytes) {
742
0
    tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
743
0
    return;
744
0
  }
745
746
0
  p = bytes;
747
748
  /*
749
   * Note: this points into state->recv_iov!
750
   */
751
0
  state->out_security_blob = data_blob_const(p, out_security_blob_length);
752
0
  p += out_security_blob_length;
753
754
0
  status = smb_bytes_pull_str(state, &state->out_native_os,
755
0
            use_unicode, bytes, num_bytes,
756
0
            p, &ret);
757
0
  if (tevent_req_nterror(req, status)) {
758
0
    return;
759
0
  }
760
0
  p += ret;
761
762
0
  status = smb_bytes_pull_str(state, &state->out_native_lm,
763
0
            use_unicode, bytes, num_bytes,
764
0
            p, &ret);
765
0
  if (tevent_req_nterror(req, status)) {
766
0
    return;
767
0
  }
768
  /* p += ret; */
769
770
0
  smb1cli_session_set_id(state->session, state->out_session_id);
771
0
  smb1cli_session_set_action(state->session, state->out_action);
772
773
0
  tevent_req_done(req);
774
0
}
775
776
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
0
{
784
0
  struct smb1cli_session_setup_ext_state *state =
785
0
    tevent_req_data(req,
786
0
    struct smb1cli_session_setup_ext_state);
787
0
  NTSTATUS status;
788
0
  struct iovec *recv_iov = NULL;
789
790
0
  if (tevent_req_is_nterror(req, &status)) {
791
0
    tevent_req_received(req);
792
0
    return status;
793
0
  }
794
795
0
  recv_iov = talloc_move(mem_ctx, &state->recv_iov);
796
0
  if (precv_iov != NULL) {
797
0
    *precv_iov = recv_iov;
798
0
  }
799
0
  if (precv_inbuf != NULL) {
800
0
    *precv_inbuf = state->inbuf;
801
0
  }
802
803
0
  *out_security_blob = state->out_security_blob;
804
805
0
  if (out_native_os != NULL) {
806
0
    *out_native_os = talloc_move(mem_ctx, &state->out_native_os);
807
0
  }
808
809
0
  if (out_native_lm != NULL) {
810
0
    *out_native_lm = talloc_move(mem_ctx, &state->out_native_lm);
811
0
  }
812
813
  /*
814
   * Return the status from the server:
815
   * NT_STATUS_MORE_PROCESSING_REQUIRED or
816
   * NT_STATUS_OK.
817
   */
818
0
  status = state->status;
819
0
  tevent_req_received(req);
820
0
  return status;
821
0
}