2 Unix SMB/CIFS implementation.
4 SMB client negotiate context management functions
6 Copyright (C) Andrew Tridgell 1994-2005
7 Copyright (C) James Myers 2003 <myersjj@samba.org>
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.
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.
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/>.
24 #include "libcli/raw/libcliraw.h"
25 #include "libcli/raw/raw_proto.h"
26 #include "system/time.h"
29 enum protocol_types prot
;
32 {PROTOCOL_CORE
,"PC NETWORK PROGRAM 1.0"},
33 {PROTOCOL_COREPLUS
,"MICROSOFT NETWORKS 1.03"},
34 {PROTOCOL_LANMAN1
,"MICROSOFT NETWORKS 3.0"},
35 {PROTOCOL_LANMAN1
,"LANMAN1.0"},
36 {PROTOCOL_LANMAN1
,"Windows for Workgroups 3.1a"},
37 {PROTOCOL_LANMAN2
,"LM1.2X002"},
38 {PROTOCOL_LANMAN2
,"DOS LANMAN2.1"},
39 {PROTOCOL_LANMAN2
,"LANMAN2.1"},
40 {PROTOCOL_LANMAN2
,"Samba"},
41 {PROTOCOL_NT1
,"NT LANMAN 1.0"},
42 {PROTOCOL_NT1
,"NT LM 0.12"},
44 /* we don't yet handle chaining a SMB transport onto SMB2 */
45 {PROTOCOL_SMB2
,"SMB 2.002"},
50 Send a negprot command.
52 struct smbcli_request
*smb_raw_negotiate_send(struct smbcli_transport
*transport
,
56 struct smbcli_request
*req
;
60 req
= smbcli_request_setup_transport(transport
, SMBnegprot
, 0, 0);
65 flags2
|= FLAGS2_32_BIT_ERROR_CODES
;
67 flags2
|= FLAGS2_UNICODE_STRINGS
;
69 flags2
|= FLAGS2_EXTENDED_ATTRIBUTES
;
70 flags2
|= FLAGS2_LONG_PATH_COMPONENTS
;
71 flags2
|= FLAGS2_IS_LONG_NAME
;
73 if (transport
->options
.use_spnego
) {
74 flags2
|= FLAGS2_EXTENDED_SECURITY
;
77 SSVAL(req
->out
.hdr
,HDR_FLG2
, flags2
);
79 /* setup the protocol strings */
80 for (i
=0; i
< ARRAY_SIZE(prots
) && prots
[i
].prot
<= maxprotocol
; i
++) {
81 smbcli_req_append_bytes(req
, (const uint8_t *)"\2", 1);
82 smbcli_req_append_string(req
, prots
[i
].name
, STR_TERMINATE
| STR_ASCII
);
85 if (!smbcli_request_send(req
)) {
86 smbcli_request_destroy(req
);
94 Send a negprot command.
96 NTSTATUS
smb_raw_negotiate_recv(struct smbcli_request
*req
)
98 struct smbcli_transport
*transport
= req
->transport
;
101 if (!smbcli_request_receive(req
) ||
102 smbcli_request_is_error(req
)) {
103 return smbcli_request_destroy(req
);
106 SMBCLI_CHECK_MIN_WCT(req
, 1);
108 protocol
= SVALS(req
->in
.vwv
, VWV(0));
110 if (protocol
>= ARRAY_SIZE(prots
) || protocol
< 0) {
111 req
->status
= NT_STATUS_UNSUCCESSFUL
;
112 return smbcli_request_destroy(req
);
115 transport
->negotiate
.protocol
= prots
[protocol
].prot
;
117 if (transport
->negotiate
.protocol
>= PROTOCOL_NT1
) {
121 SMBCLI_CHECK_WCT(req
, 17);
122 transport
->negotiate
.sec_mode
= CVAL(req
->in
.vwv
,VWV(1));
123 transport
->negotiate
.max_mux
= SVAL(req
->in
.vwv
,VWV(1)+1);
124 transport
->negotiate
.max_xmit
= IVAL(req
->in
.vwv
,VWV(3)+1);
125 transport
->negotiate
.sesskey
= IVAL(req
->in
.vwv
,VWV(7)+1);
126 transport
->negotiate
.capabilities
= IVAL(req
->in
.vwv
,VWV(9)+1);
128 /* this time arrives in real GMT */
129 ntt
= smbcli_pull_nttime(req
->in
.vwv
, VWV(11)+1);
130 transport
->negotiate
.server_time
= nt_time_to_unix(ntt
);
131 transport
->negotiate
.server_zone
= SVALS(req
->in
.vwv
,VWV(15)+1) * 60;
132 transport
->negotiate
.key_len
= CVAL(req
->in
.vwv
,VWV(16)+1);
134 if (transport
->negotiate
.capabilities
& CAP_EXTENDED_SECURITY
) {
135 if (req
->in
.data_size
< 16) {
138 transport
->negotiate
.server_guid
= smbcli_req_pull_blob(&req
->in
.bufinfo
, transport
, req
->in
.data
, 16);
139 transport
->negotiate
.secblob
= smbcli_req_pull_blob(&req
->in
.bufinfo
, transport
, req
->in
.data
+ 16, req
->in
.data_size
- 16);
141 if (req
->in
.data_size
< (transport
->negotiate
.key_len
)) {
144 transport
->negotiate
.secblob
= smbcli_req_pull_blob(&req
->in
.bufinfo
, transport
, req
->in
.data
, transport
->negotiate
.key_len
);
145 smbcli_req_pull_string(&req
->in
.bufinfo
, transport
, &transport
->negotiate
.server_domain
,
146 req
->in
.data
+transport
->negotiate
.key_len
,
147 req
->in
.data_size
-transport
->negotiate
.key_len
, STR_UNICODE
|STR_NOALIGN
);
148 /* here comes the server name */
151 if (transport
->negotiate
.capabilities
& CAP_RAW_MODE
) {
152 transport
->negotiate
.readbraw_supported
= true;
153 transport
->negotiate
.writebraw_supported
= true;
156 if (transport
->negotiate
.capabilities
& CAP_LOCK_AND_READ
)
157 transport
->negotiate
.lockread_supported
= true;
158 } else if (transport
->negotiate
.protocol
>= PROTOCOL_LANMAN1
) {
159 SMBCLI_CHECK_WCT(req
, 13);
160 transport
->negotiate
.sec_mode
= SVAL(req
->in
.vwv
,VWV(1));
161 transport
->negotiate
.max_xmit
= SVAL(req
->in
.vwv
,VWV(2));
162 transport
->negotiate
.sesskey
= IVAL(req
->in
.vwv
,VWV(6));
163 transport
->negotiate
.server_zone
= SVALS(req
->in
.vwv
,VWV(10)) * 60;
165 /* this time is converted to GMT by raw_pull_dos_date */
166 transport
->negotiate
.server_time
= raw_pull_dos_date(transport
,
168 if ((SVAL(req
->in
.vwv
,VWV(5)) & 0x1)) {
169 transport
->negotiate
.readbraw_supported
= 1;
171 if ((SVAL(req
->in
.vwv
,VWV(5)) & 0x2)) {
172 transport
->negotiate
.writebraw_supported
= 1;
174 transport
->negotiate
.secblob
= smbcli_req_pull_blob(&req
->in
.bufinfo
, transport
,
175 req
->in
.data
, req
->in
.data_size
);
177 /* the old core protocol */
178 transport
->negotiate
.sec_mode
= 0;
179 transport
->negotiate
.server_time
= time(NULL
);
180 transport
->negotiate
.max_xmit
= transport
->options
.max_xmit
;
181 transport
->negotiate
.server_zone
= get_time_zone(transport
->negotiate
.server_time
);
184 /* a way to force ascii SMB */
185 if (!transport
->options
.unicode
) {
186 transport
->negotiate
.capabilities
&= ~CAP_UNICODE
;
189 if (!transport
->options
.ntstatus_support
) {
190 transport
->negotiate
.capabilities
&= ~CAP_STATUS32
;
193 if (!transport
->options
.use_level2_oplocks
) {
194 transport
->negotiate
.capabilities
&= ~CAP_LEVEL_II_OPLOCKS
;
198 return smbcli_request_destroy(req
);
203 Send a negprot command (sync interface)
205 NTSTATUS
smb_raw_negotiate(struct smbcli_transport
*transport
, bool unicode
, int maxprotocol
)
207 struct smbcli_request
*req
= smb_raw_negotiate_send(transport
, unicode
, maxprotocol
);
208 return smb_raw_negotiate_recv(req
);