2 Unix SMB/CIFS implementation.
3 SMB client negotiate context management functions
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) James Myers 2003 <myersjj@samba.org>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"},
29 {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"},
30 {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"},
31 {PROTOCOL_LANMAN1,"LANMAN1.0"},
32 {PROTOCOL_LANMAN1,"Windows for Workgroups 3.1a"},
33 {PROTOCOL_LANMAN2,"LM1.2X002"},
34 {PROTOCOL_LANMAN2,"DOS LANMAN2.1"},
35 {PROTOCOL_LANMAN2,"Samba"},
36 {PROTOCOL_NT1,"NT LANMAN 1.0"},
37 {PROTOCOL_NT1,"NT LM 0.12"},
40 /****************************************************************************
41 Send a negprot command.
42 ****************************************************************************/
43 struct cli_request *smb_negprot_send(struct cli_transport *transport, int maxprotocol)
45 struct cli_request *req;
48 req = cli_request_setup_transport(transport, SMBnegprot, 0, 0);
53 /* setup the protocol strings */
54 for (i=0; i < ARRAY_SIZE(prots) && prots[i].prot <= maxprotocol; i++) {
55 cli_req_append_bytes(req, "\2", 1);
56 cli_req_append_string(req, prots[i].name, STR_TERMINATE | STR_ASCII);
59 if (!cli_request_send(req)) {
60 cli_request_destroy(req);
67 /****************************************************************************
68 Send a negprot command.
69 ****************************************************************************/
70 NTSTATUS smb_raw_negotiate(struct cli_transport *transport)
72 struct cli_request *req;
75 req = smb_negprot_send(transport, PROTOCOL_NT1);
77 return NT_STATUS_UNSUCCESSFUL;
80 if (!cli_request_receive(req) ||
81 cli_request_is_error(req)) {
82 return cli_request_destroy(req);
85 CLI_CHECK_MIN_WCT(req, 1);
87 protocol = SVALS(req->in.vwv, VWV(0));
89 if (protocol >= ARRAY_SIZE(prots) || protocol < 0) {
90 req->status = NT_STATUS_UNSUCCESSFUL;
91 return cli_request_destroy(req);
94 transport->negotiate.protocol = prots[protocol].prot;
96 if (transport->negotiate.protocol >= PROTOCOL_NT1) {
100 CLI_CHECK_WCT(req, 17);
101 transport->negotiate.sec_mode = CVAL(req->in.vwv,VWV(1));
102 transport->negotiate.max_mux = SVAL(req->in.vwv,VWV(1)+1);
103 transport->negotiate.max_xmit = IVAL(req->in.vwv,VWV(3)+1);
104 transport->negotiate.sesskey = IVAL(req->in.vwv,VWV(7)+1);
105 transport->negotiate.server_zone = SVALS(req->in.vwv,VWV(15)+1) * 60;
107 /* this time arrives in real GMT */
108 ntt = cli_pull_nttime(req->in.vwv, VWV(11)+1);
109 transport->negotiate.server_time = nt_time_to_unix(&ntt);
110 transport->negotiate.capabilities = IVAL(req->in.vwv,VWV(9)+1);
112 transport->negotiate.secblob = cli_req_pull_blob(req, transport->mem_ctx, req->in.data, req->in.data_size);
113 if (transport->negotiate.capabilities & CAP_RAW_MODE) {
114 transport->negotiate.readbraw_supported = True;
115 transport->negotiate.writebraw_supported = True;
118 /* work out if they sent us a workgroup */
119 if ((transport->negotiate.capabilities & CAP_EXTENDED_SECURITY) &&
120 req->in.data_size > 16) {
121 cli_req_pull_string(req, transport->mem_ctx, &transport->negotiate.server_domain,
123 req->in.data_size-16, STR_UNICODE|STR_NOALIGN);
125 } else if (transport->negotiate.protocol >= PROTOCOL_LANMAN1) {
126 CLI_CHECK_WCT(req, 13);
127 transport->negotiate.sec_mode = SVAL(req->in.vwv,VWV(1));
128 transport->negotiate.max_xmit = SVAL(req->in.vwv,VWV(2));
129 transport->negotiate.sesskey = IVAL(req->in.vwv,VWV(6));
130 transport->negotiate.server_zone = SVALS(req->in.vwv,VWV(10)) * 60;
132 /* this time is converted to GMT by make_unix_date */
133 transport->negotiate.server_time = make_unix_date(req->in.vwv+VWV(8));
134 if ((SVAL(req->in.vwv,VWV(5)) & 0x1)) {
135 transport->negotiate.readbraw_supported = 1;
137 if ((SVAL(req->in.vwv,VWV(5)) & 0x2)) {
138 transport->negotiate.writebraw_supported = 1;
140 transport->negotiate.secblob = cli_req_pull_blob(req, transport->mem_ctx,
141 req->in.data, req->in.data_size);
143 /* the old core protocol */
144 transport->negotiate.sec_mode = 0;
145 transport->negotiate.server_time = time(NULL);
146 transport->negotiate.max_xmit = ~0;
147 transport->negotiate.server_zone = TimeDiff(time(NULL));
150 /* a way to force ascii SMB */
151 if (getenv("CLI_FORCE_ASCII")) {
152 transport->negotiate.capabilities &= ~CAP_UNICODE;
156 return cli_request_destroy(req);