Coverage Report

Created: 2025-11-16 06:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/source4/libcli/raw/rawnegotiate.c
Line
Count
Source
1
/*
2
   Unix SMB/CIFS implementation.
3
4
   SMB client negotiate context management functions
5
6
   Copyright (C) Andrew Tridgell 1994-2005
7
   Copyright (C) James Myers 2003 <myersjj@samba.org>
8
9
   This program is free software; you can redistribute it and/or modify
10
   it under the terms of the GNU General Public License as published by
11
   the Free Software Foundation; either version 3 of the License, or
12
   (at your option) any later version.
13
14
   This program is distributed in the hope that it will be useful,
15
   but WITHOUT ANY WARRANTY; without even the implied warranty of
16
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
   GNU General Public License for more details.
18
19
   You should have received a copy of the GNU General Public License
20
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
*/
22
23
#include "includes.h"
24
#include <tevent.h>
25
#include "system/time.h"
26
#include "libcli/raw/libcliraw.h"
27
#include "libcli/raw/raw_proto.h"
28
#include "../libcli/smb/smbXcli_base.h"
29
#include "../lib/util/tevent_ntstatus.h"
30
31
NTSTATUS smb_raw_negotiate_fill_transport(struct smbcli_transport *transport)
32
0
{
33
0
  struct smbcli_negotiate *n = &transport->negotiate;
34
0
  struct smbXcli_conn *c = transport->conn;
35
0
  NTTIME ntt;
36
37
0
  n->protocol = smbXcli_conn_protocol(c);
38
0
  if (n->protocol > PROTOCOL_NT1) {
39
0
    return NT_STATUS_REVISION_MISMATCH;
40
0
  }
41
42
0
  n->sec_mode = smb1cli_conn_server_security_mode(c);
43
0
  n->max_mux  = smbXcli_conn_max_requests(c);
44
0
  n->max_xmit = smb1cli_conn_max_xmit(c);
45
0
  n->sesskey  = smb1cli_conn_server_session_key(c);
46
0
  n->capabilities = smb1cli_conn_capabilities(c);;
47
48
  /* this time arrives in real GMT */
49
0
  ntt = smbXcli_conn_server_system_time(c);
50
0
  n->server_time = nt_time_to_unix(ntt);
51
0
  n->server_zone = smb1cli_conn_server_time_zone(c);
52
53
0
  if (n->capabilities & CAP_EXTENDED_SECURITY) {
54
0
    const DATA_BLOB *b = smbXcli_conn_server_gss_blob(c);
55
0
    if (b) {
56
0
      n->secblob = *b;
57
0
    }
58
0
  } else {
59
0
    const uint8_t *p = smb1cli_conn_server_challenge(c);
60
0
    if (p) {
61
0
      n->secblob = data_blob_const(p, 8);
62
0
    }
63
0
  }
64
65
0
  n->readbraw_supported = smb1cli_conn_server_readbraw(c);
66
0
  n->readbraw_supported = smb1cli_conn_server_writebraw(c);
67
0
  n->lockread_supported = smb1cli_conn_server_lockread(c);
68
69
0
  return NT_STATUS_OK;
70
0
}
71
72
struct smb_raw_negotiate_state {
73
  struct smbcli_transport *transport;
74
};
75
76
static void smb_raw_negotiate_done(struct tevent_req *subreq);
77
78
struct tevent_req *smb_raw_negotiate_send(TALLOC_CTX *mem_ctx,
79
            struct tevent_context *ev,
80
            struct smbcli_transport *transport,
81
            int minprotocol,
82
            int maxprotocol)
83
0
{
84
0
  struct tevent_req *req;
85
0
  struct smb_raw_negotiate_state *state;
86
0
  struct tevent_req *subreq;
87
0
  uint32_t timeout_msec = transport->options.request_timeout * 1000;
88
89
0
  req = tevent_req_create(mem_ctx, &state,
90
0
        struct smb_raw_negotiate_state);;
91
0
  if (req == NULL) {
92
0
    return NULL;
93
0
  }
94
0
  state->transport = transport;
95
96
0
  if (maxprotocol > PROTOCOL_NT1) {
97
0
    maxprotocol = PROTOCOL_NT1;
98
0
  }
99
100
0
  if (minprotocol > maxprotocol) {
101
0
    minprotocol = maxprotocol;
102
0
  }
103
104
0
  subreq = smbXcli_negprot_send(state, ev,
105
0
              transport->conn,
106
0
              timeout_msec,
107
0
              minprotocol,
108
0
              maxprotocol,
109
0
              transport->options.max_credits,
110
0
              NULL);
111
0
  if (tevent_req_nomem(subreq, req)) {
112
0
    return tevent_req_post(req, ev);
113
0
  }
114
0
  tevent_req_set_callback(subreq, smb_raw_negotiate_done, req);
115
116
0
  return req;
117
0
}
118
119
static void smb_raw_negotiate_done(struct tevent_req *subreq)
120
0
{
121
0
  struct tevent_req *req =
122
0
    tevent_req_callback_data(subreq,
123
0
    struct tevent_req);
124
0
  struct smb_raw_negotiate_state *state =
125
0
    tevent_req_data(req,
126
0
    struct smb_raw_negotiate_state);
127
0
  NTSTATUS status;
128
129
0
  status = smbXcli_negprot_recv(subreq, NULL, NULL);
130
0
  TALLOC_FREE(subreq);
131
0
  if (tevent_req_nterror(req, status)) {
132
0
    return;
133
0
  }
134
135
0
  status = smb_raw_negotiate_fill_transport(state->transport);
136
0
  if (tevent_req_nterror(req, status)) {
137
0
    return;
138
0
  }
139
140
0
  tevent_req_done(req);
141
0
}
142
143
/*
144
 Send a negprot command.
145
*/
146
NTSTATUS smb_raw_negotiate_recv(struct tevent_req *req)
147
0
{
148
0
  return tevent_req_simple_recv_ntstatus(req);
149
0
}
150
151
152
/*
153
 Send a negprot command (sync interface)
154
*/
155
NTSTATUS smb_raw_negotiate(struct smbcli_transport *transport, bool unicode,
156
         int minprotocol, int maxprotocol)
157
0
{
158
0
  NTSTATUS status;
159
0
  struct tevent_req *subreq = NULL;
160
0
  bool ok;
161
162
0
  subreq = smb_raw_negotiate_send(transport,
163
0
          transport->ev,
164
0
          transport,
165
0
          minprotocol,
166
0
          maxprotocol);
167
0
  if (subreq == NULL) {
168
0
    status = NT_STATUS_NO_MEMORY;
169
0
    goto failed;
170
0
  }
171
172
0
  ok = tevent_req_poll(subreq, transport->ev);
173
0
  if (!ok) {
174
0
    status = map_nt_error_from_unix_common(errno);
175
0
    goto failed;
176
0
  }
177
178
0
  status = smb_raw_negotiate_recv(subreq);
179
180
0
failed:
181
  TALLOC_FREE(subreq);
182
0
  return status;
183
0
}