blob: bbdda99dce610364b71b5218cb061b3dfc577cd9 [file] [log] [blame]
Steve French39798772006-05-31 22:40:51 +00001/*
2 * fs/cifs/sess.c
3 *
4 * SMB/CIFS session setup handling routines
5 *
6 * Copyright (c) International Business Machines Corp., 2006
7 * Author(s): Steve French (sfrench@us.ibm.com)
8 *
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
13 *
14 * This library 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
17 * the GNU Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24#include "cifspdu.h"
25#include "cifsglob.h"
26#include "cifsproto.h"
27#include "cifs_unicode.h"
28#include "cifs_debug.h"
29#include "ntlmssp.h"
30#include "nterr.h"
Steve French9c535882006-06-01 05:09:10 +000031#include <linux/utsname.h>
Steve French39798772006-05-31 22:40:51 +000032
Steve French39798772006-05-31 22:40:51 +000033extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
34 unsigned char *p24);
35
Steve French39798772006-05-31 22:40:51 +000036static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB)
37{
38 __u32 capabilities = 0;
39
40 /* init fields common to all four types of SessSetup */
41 /* note that header is initialized to zero in header_assemble */
42 pSMB->req.AndXCommand = 0xFF;
43 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
44 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
45
46 /* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */
47
48 /* BB verify whether signing required on neg or just on auth frame
49 (and NTLM case) */
50
51 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
52 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
53
54 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
55 pSMB->req.hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
56
57 if (ses->capabilities & CAP_UNICODE) {
58 pSMB->req.hdr.Flags2 |= SMBFLG2_UNICODE;
59 capabilities |= CAP_UNICODE;
60 }
61 if (ses->capabilities & CAP_STATUS32) {
62 pSMB->req.hdr.Flags2 |= SMBFLG2_ERR_STATUS;
63 capabilities |= CAP_STATUS32;
64 }
65 if (ses->capabilities & CAP_DFS) {
66 pSMB->req.hdr.Flags2 |= SMBFLG2_DFS;
67 capabilities |= CAP_DFS;
68 }
69 if (ses->capabilities & CAP_UNIX) {
70 capabilities |= CAP_UNIX;
71 }
72
73 /* BB check whether to init vcnum BB */
74 return capabilities;
75}
76
Steve French7c7b25b2006-06-01 19:20:10 +000077static void unicode_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
Steve French39798772006-05-31 22:40:51 +000078 const struct nls_table * nls_cp)
79{
80 char * bcc_ptr = *pbcc_area;
81 int bytes_ret = 0;
82
83 /* BB FIXME add check that strings total less
84 than 335 or will need to send them as arrays */
85
Steve French0223cf02006-06-27 19:50:57 +000086 /* unicode strings, must be word aligned before the call */
87/* if ((long) bcc_ptr % 2) {
Steve French39798772006-05-31 22:40:51 +000088 *bcc_ptr = 0;
89 bcc_ptr++;
Steve French0223cf02006-06-27 19:50:57 +000090 } */
Steve French39798772006-05-31 22:40:51 +000091 /* copy user */
92 if(ses->userName == NULL) {
Steve French6e659c62006-11-08 23:10:46 +000093 /* null user mount */
94 *bcc_ptr = 0;
95 *(bcc_ptr+1) = 0;
Steve French39798772006-05-31 22:40:51 +000096 } else { /* 300 should be long enough for any conceivable user name */
97 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->userName,
98 300, nls_cp);
99 }
100 bcc_ptr += 2 * bytes_ret;
101 bcc_ptr += 2; /* account for null termination */
102 /* copy domain */
Steve French6e659c62006-11-08 23:10:46 +0000103 if(ses->domainName == NULL) {
104 /* Sending null domain better than using a bogus domain name (as
105 we did briefly in 2.6.18) since server will use its default */
106 *bcc_ptr = 0;
107 *(bcc_ptr+1) = 0;
108 bytes_ret = 0;
109 } else
Steve French39798772006-05-31 22:40:51 +0000110 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->domainName,
111 256, nls_cp);
112 bcc_ptr += 2 * bytes_ret;
113 bcc_ptr += 2; /* account for null terminator */
114
115 /* Copy OS version */
116 bytes_ret = cifs_strtoUCS((__le16 *)bcc_ptr, "Linux version ", 32,
117 nls_cp);
118 bcc_ptr += 2 * bytes_ret;
Serge E. Hallyn96b644b2006-10-02 02:18:13 -0700119 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, init_utsname()->release,
Steve French39798772006-05-31 22:40:51 +0000120 32, nls_cp);
121 bcc_ptr += 2 * bytes_ret;
122 bcc_ptr += 2; /* trailing null */
123
124 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
125 32, nls_cp);
126 bcc_ptr += 2 * bytes_ret;
127 bcc_ptr += 2; /* trailing null */
128
129 *pbcc_area = bcc_ptr;
130}
131
Steve French7c7b25b2006-06-01 19:20:10 +0000132static void ascii_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
Steve French39798772006-05-31 22:40:51 +0000133 const struct nls_table * nls_cp)
134{
135 char * bcc_ptr = *pbcc_area;
136
137 /* copy user */
138 /* BB what about null user mounts - check that we do this BB */
139 /* copy user */
140 if(ses->userName == NULL) {
141 /* BB what about null user mounts - check that we do this BB */
142 } else { /* 300 should be long enough for any conceivable user name */
143 strncpy(bcc_ptr, ses->userName, 300);
144 }
145 /* BB improve check for overflow */
Steve French750d1152006-06-27 06:28:30 +0000146 bcc_ptr += strnlen(ses->userName, 300);
Steve French39798772006-05-31 22:40:51 +0000147 *bcc_ptr = 0;
148 bcc_ptr++; /* account for null termination */
149
150 /* copy domain */
151
Steve French6e659c62006-11-08 23:10:46 +0000152 if(ses->domainName != NULL) {
Steve French39798772006-05-31 22:40:51 +0000153 strncpy(bcc_ptr, ses->domainName, 256);
154 bcc_ptr += strnlen(ses->domainName, 256);
Steve French6e659c62006-11-08 23:10:46 +0000155 } /* else we will send a null domain name
156 so the server will default to its own domain */
Steve French39798772006-05-31 22:40:51 +0000157 *bcc_ptr = 0;
158 bcc_ptr++;
159
160 /* BB check for overflow here */
161
162 strcpy(bcc_ptr, "Linux version ");
163 bcc_ptr += strlen("Linux version ");
Serge E. Hallyn96b644b2006-10-02 02:18:13 -0700164 strcpy(bcc_ptr, init_utsname()->release);
165 bcc_ptr += strlen(init_utsname()->release) + 1;
Steve French39798772006-05-31 22:40:51 +0000166
167 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
168 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
169
170 *pbcc_area = bcc_ptr;
171}
172
Steve French7c7b25b2006-06-01 19:20:10 +0000173static int decode_unicode_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses,
Steve French39798772006-05-31 22:40:51 +0000174 const struct nls_table * nls_cp)
175{
176 int rc = 0;
177 int words_left, len;
178 char * data = *pbcc_area;
179
180
181
182 cFYI(1,("bleft %d",bleft));
183
184
185 /* word align, if bytes remaining is not even */
186 if(bleft % 2) {
187 bleft--;
188 data++;
189 }
190 words_left = bleft / 2;
191
192 /* save off server operating system */
193 len = UniStrnlen((wchar_t *) data, words_left);
194
195/* We look for obvious messed up bcc or strings in response so we do not go off
196 the end since (at least) WIN2K and Windows XP have a major bug in not null
197 terminating last Unicode string in response */
198 if(len >= words_left)
199 return rc;
200
201 if(ses->serverOS)
202 kfree(ses->serverOS);
203 /* UTF-8 string will not grow more than four times as big as UCS-16 */
204 ses->serverOS = kzalloc(4 * len, GFP_KERNEL);
205 if(ses->serverOS != NULL) {
206 cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len,
207 nls_cp);
208 }
209 data += 2 * (len + 1);
210 words_left -= len + 1;
211
212 /* save off server network operating system */
213 len = UniStrnlen((wchar_t *) data, words_left);
214
215 if(len >= words_left)
216 return rc;
217
218 if(ses->serverNOS)
219 kfree(ses->serverNOS);
220 ses->serverNOS = kzalloc(4 * len, GFP_KERNEL); /* BB this is wrong length FIXME BB */
221 if(ses->serverNOS != NULL) {
222 cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len,
223 nls_cp);
224 if(strncmp(ses->serverNOS, "NT LAN Manager 4",16) == 0) {
225 cFYI(1,("NT4 server"));
226 ses->flags |= CIFS_SES_NT4;
227 }
228 }
229 data += 2 * (len + 1);
230 words_left -= len + 1;
231
232 /* save off server domain */
233 len = UniStrnlen((wchar_t *) data, words_left);
234
235 if(len > words_left)
236 return rc;
237
238 if(ses->serverDomain)
239 kfree(ses->serverDomain);
240 ses->serverDomain = kzalloc(2 * (len + 1), GFP_KERNEL); /* BB FIXME wrong length */
241 if(ses->serverDomain != NULL) {
242 cifs_strfromUCS_le(ses->serverDomain, (__le16 *)data, len,
243 nls_cp);
244 ses->serverDomain[2*len] = 0;
245 ses->serverDomain[(2*len) + 1] = 0;
246 }
247 data += 2 * (len + 1);
248 words_left -= len + 1;
249
250 cFYI(1,("words left: %d",words_left));
251
252 return rc;
253}
254
Steve French7c7b25b2006-06-01 19:20:10 +0000255static int decode_ascii_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses,
Steve French39798772006-05-31 22:40:51 +0000256 const struct nls_table * nls_cp)
257{
258 int rc = 0;
259 int len;
260 char * bcc_ptr = *pbcc_area;
261
262 cFYI(1,("decode sessetup ascii. bleft %d", bleft));
263
264 len = strnlen(bcc_ptr, bleft);
265 if(len >= bleft)
266 return rc;
267
268 if(ses->serverOS)
269 kfree(ses->serverOS);
270
271 ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
272 if(ses->serverOS)
273 strncpy(ses->serverOS, bcc_ptr, len);
Steve French9ac00b72006-09-30 04:13:17 +0000274 if(strncmp(ses->serverOS, "OS/2",4) == 0) {
275 cFYI(1,("OS/2 server"));
276 ses->flags |= CIFS_SES_OS2;
277 }
Steve French39798772006-05-31 22:40:51 +0000278
279 bcc_ptr += len + 1;
280 bleft -= len + 1;
281
282 len = strnlen(bcc_ptr, bleft);
283 if(len >= bleft)
284 return rc;
285
286 if(ses->serverNOS)
287 kfree(ses->serverNOS);
288
289 ses->serverNOS = kzalloc(len + 1, GFP_KERNEL);
290 if(ses->serverNOS)
291 strncpy(ses->serverNOS, bcc_ptr, len);
292
293 bcc_ptr += len + 1;
294 bleft -= len + 1;
295
296 len = strnlen(bcc_ptr, bleft);
297 if(len > bleft)
298 return rc;
299
Steve French9ac00b72006-09-30 04:13:17 +0000300 /* No domain field in LANMAN case. Domain is
301 returned by old servers in the SMB negprot response */
302 /* BB For newer servers which do not support Unicode,
303 but thus do return domain here we could add parsing
304 for it later, but it is not very important */
Steve French39798772006-05-31 22:40:51 +0000305 cFYI(1,("ascii: bytes left %d",bleft));
306
307 return rc;
308}
309
310int
311CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
312 const struct nls_table *nls_cp)
313{
314 int rc = 0;
315 int wct;
Steve French39798772006-05-31 22:40:51 +0000316 struct smb_hdr *smb_buf;
317 char *bcc_ptr;
Steve French750d1152006-06-27 06:28:30 +0000318 char *str_area;
Steve French39798772006-05-31 22:40:51 +0000319 SESSION_SETUP_ANDX *pSMB;
320 __u32 capabilities;
321 int count;
322 int resp_buf_type = 0;
Steve French750d1152006-06-27 06:28:30 +0000323 struct kvec iov[2];
Steve French39798772006-05-31 22:40:51 +0000324 enum securityEnum type;
325 __u16 action;
326 int bytes_remaining;
Steve French254e55e2006-06-04 05:53:15 +0000327
Steve French39798772006-05-31 22:40:51 +0000328 if(ses == NULL)
329 return -EINVAL;
330
331 type = ses->server->secType;
Steve Frenchf40c5622006-06-28 00:13:38 +0000332
333 cFYI(1,("sess setup type %d",type));
Steve French39798772006-05-31 22:40:51 +0000334 if(type == LANMAN) {
335#ifndef CONFIG_CIFS_WEAK_PW_HASH
336 /* LANMAN and plaintext are less secure and off by default.
337 So we make this explicitly be turned on in kconfig (in the
338 build) and turned on at runtime (changed from the default)
339 in proc/fs/cifs or via mount parm. Unfortunately this is
340 needed for old Win (e.g. Win95), some obscure NAS and OS/2 */
341 return -EOPNOTSUPP;
342#endif
343 wct = 10; /* lanman 2 style sessionsetup */
Steve French9312f672006-06-04 22:21:07 +0000344 } else if((type == NTLM) || (type == NTLMv2)) {
345 /* For NTLMv2 failures eventually may need to retry NTLM */
Steve French39798772006-05-31 22:40:51 +0000346 wct = 13; /* old style NTLM sessionsetup */
Steve French9312f672006-06-04 22:21:07 +0000347 } else /* same size for negotiate or auth, NTLMSSP or extended security */
Steve French39798772006-05-31 22:40:51 +0000348 wct = 12;
349
350 rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses,
351 (void **)&smb_buf);
352 if(rc)
353 return rc;
354
355 pSMB = (SESSION_SETUP_ANDX *)smb_buf;
356
357 capabilities = cifs_ssetup_hdr(ses, pSMB);
Steve French750d1152006-06-27 06:28:30 +0000358
359 /* we will send the SMB in two pieces,
360 a fixed length beginning part, and a
361 second part which will include the strings
362 and rest of bcc area, in order to avoid having
363 to do a large buffer 17K allocation */
364 iov[0].iov_base = (char *)pSMB;
365 iov[0].iov_len = smb_buf->smb_buf_length + 4;
366
367 /* 2000 big enough to fit max user, domain, NOS name etc. */
368 str_area = kmalloc(2000, GFP_KERNEL);
369 bcc_ptr = str_area;
Steve French39798772006-05-31 22:40:51 +0000370
Steve French9ac00b72006-09-30 04:13:17 +0000371 ses->flags &= ~CIFS_SES_LANMAN;
372
Steve French39798772006-05-31 22:40:51 +0000373 if(type == LANMAN) {
374#ifdef CONFIG_CIFS_WEAK_PW_HASH
Steve French7c7b25b2006-06-01 19:20:10 +0000375 char lnm_session_key[CIFS_SESS_KEY_SIZE];
Steve French39798772006-05-31 22:40:51 +0000376
377 /* no capabilities flags in old lanman negotiation */
378
Steve French5ddaa682006-08-15 13:35:48 +0000379 pSMB->old_req.PasswordLength = cpu_to_le16(CIFS_SESS_KEY_SIZE);
Steve French39798772006-05-31 22:40:51 +0000380 /* BB calculate hash with password */
381 /* and copy into bcc */
382
Steve French7c7b25b2006-06-01 19:20:10 +0000383 calc_lanman_hash(ses, lnm_session_key);
Steve French9ac00b72006-09-30 04:13:17 +0000384 ses->flags |= CIFS_SES_LANMAN;
Steve French750d1152006-06-27 06:28:30 +0000385/* #ifdef CONFIG_CIFS_DEBUG2
Steve French39798772006-05-31 22:40:51 +0000386 cifs_dump_mem("cryptkey: ",ses->server->cryptKey,
Steve French7c7b25b2006-06-01 19:20:10 +0000387 CIFS_SESS_KEY_SIZE);
Steve French750d1152006-06-27 06:28:30 +0000388#endif */
Steve French7c7b25b2006-06-01 19:20:10 +0000389 memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_SESS_KEY_SIZE);
390 bcc_ptr += CIFS_SESS_KEY_SIZE;
Steve French39798772006-05-31 22:40:51 +0000391
392 /* can not sign if LANMAN negotiated so no need
393 to calculate signing key? but what if server
394 changed to do higher than lanman dialect and
395 we reconnected would we ever calc signing_key? */
396
Steve French750d1152006-06-27 06:28:30 +0000397 cFYI(1,("Negotiating LANMAN setting up strings"));
Steve French39798772006-05-31 22:40:51 +0000398 /* Unicode not allowed for LANMAN dialects */
399 ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
400#endif
401 } else if (type == NTLM) {
Steve French7c7b25b2006-06-01 19:20:10 +0000402 char ntlm_session_key[CIFS_SESS_KEY_SIZE];
Steve French39798772006-05-31 22:40:51 +0000403
404 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
405 pSMB->req_no_secext.CaseInsensitivePasswordLength =
Steve French7c7b25b2006-06-01 19:20:10 +0000406 cpu_to_le16(CIFS_SESS_KEY_SIZE);
Steve French39798772006-05-31 22:40:51 +0000407 pSMB->req_no_secext.CaseSensitivePasswordLength =
Steve French7c7b25b2006-06-01 19:20:10 +0000408 cpu_to_le16(CIFS_SESS_KEY_SIZE);
Steve French39798772006-05-31 22:40:51 +0000409
410 /* calculate session key */
411 SMBNTencrypt(ses->password, ses->server->cryptKey,
412 ntlm_session_key);
413
414 if(first_time) /* should this be moved into common code
415 with similar ntlmv2 path? */
Steve French750d1152006-06-27 06:28:30 +0000416 cifs_calculate_mac_key(ses->server->mac_signing_key,
Steve French39798772006-05-31 22:40:51 +0000417 ntlm_session_key, ses->password);
418 /* copy session key */
419
Steve French7c7b25b2006-06-01 19:20:10 +0000420 memcpy(bcc_ptr, (char *)ntlm_session_key,CIFS_SESS_KEY_SIZE);
421 bcc_ptr += CIFS_SESS_KEY_SIZE;
422 memcpy(bcc_ptr, (char *)ntlm_session_key,CIFS_SESS_KEY_SIZE);
423 bcc_ptr += CIFS_SESS_KEY_SIZE;
Steve French0223cf02006-06-27 19:50:57 +0000424 if(ses->capabilities & CAP_UNICODE) {
425 /* unicode strings must be word aligned */
426 if (iov[0].iov_len % 2) {
427 *bcc_ptr = 0;
428 bcc_ptr++;
429 }
Steve French7c7b25b2006-06-01 19:20:10 +0000430 unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
Steve French0223cf02006-06-27 19:50:57 +0000431 } else
Steve French7c7b25b2006-06-01 19:20:10 +0000432 ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
433 } else if (type == NTLMv2) {
Steve French6d027cf2006-06-05 16:26:05 +0000434 char * v2_sess_key =
435 kmalloc(sizeof(struct ntlmv2_resp), GFP_KERNEL);
Steve Frenchf64b23a2006-06-05 05:27:37 +0000436
437 /* BB FIXME change all users of v2_sess_key to
438 struct ntlmv2_resp */
Steve French7c7b25b2006-06-01 19:20:10 +0000439
440 if(v2_sess_key == NULL) {
441 cifs_small_buf_release(smb_buf);
442 return -ENOMEM;
443 }
444
445 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
446
447 /* LM2 password would be here if we supported it */
448 pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
449 /* cpu_to_le16(LM2_SESS_KEY_SIZE); */
450
451 pSMB->req_no_secext.CaseSensitivePasswordLength =
Steve Frenchf64b23a2006-06-05 05:27:37 +0000452 cpu_to_le16(sizeof(struct ntlmv2_resp));
Steve French7c7b25b2006-06-01 19:20:10 +0000453
454 /* calculate session key */
Steve French1717ffc2006-06-08 05:41:32 +0000455 setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp);
Steve French7c7b25b2006-06-01 19:20:10 +0000456 if(first_time) /* should this be moved into common code
457 with similar ntlmv2 path? */
458 /* cifs_calculate_ntlmv2_mac_key(ses->server->mac_signing_key,
459 response BB FIXME, v2_sess_key); */
460
461 /* copy session key */
462
463 /* memcpy(bcc_ptr, (char *)ntlm_session_key,LM2_SESS_KEY_SIZE);
464 bcc_ptr += LM2_SESS_KEY_SIZE; */
Steve Frenchf64b23a2006-06-05 05:27:37 +0000465 memcpy(bcc_ptr, (char *)v2_sess_key, sizeof(struct ntlmv2_resp));
466 bcc_ptr += sizeof(struct ntlmv2_resp);
467 kfree(v2_sess_key);
Steve French0223cf02006-06-27 19:50:57 +0000468 if(ses->capabilities & CAP_UNICODE) {
469 if(iov[0].iov_len % 2) {
470 *bcc_ptr = 0;
471 } bcc_ptr++;
Steve French39798772006-05-31 22:40:51 +0000472 unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
Steve French0223cf02006-06-27 19:50:57 +0000473 } else
Steve French39798772006-05-31 22:40:51 +0000474 ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
475 } else /* NTLMSSP or SPNEGO */ {
476 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
477 capabilities |= CAP_EXTENDED_SECURITY;
478 pSMB->req.Capabilities = cpu_to_le32(capabilities);
479 /* BB set password lengths */
480 }
481
Steve French750d1152006-06-27 06:28:30 +0000482 count = (long) bcc_ptr - (long) str_area;
Steve French39798772006-05-31 22:40:51 +0000483 smb_buf->smb_buf_length += count;
484
Steve French39798772006-05-31 22:40:51 +0000485 BCC_LE(smb_buf) = cpu_to_le16(count);
486
Steve French750d1152006-06-27 06:28:30 +0000487 iov[1].iov_base = str_area;
488 iov[1].iov_len = count;
489 rc = SendReceive2(xid, ses, iov, 2 /* num_iovecs */, &resp_buf_type, 0);
Steve French39798772006-05-31 22:40:51 +0000490 /* SMB request buf freed in SendReceive2 */
491
492 cFYI(1,("ssetup rc from sendrecv2 is %d",rc));
493 if(rc)
494 goto ssetup_exit;
495
496 pSMB = (SESSION_SETUP_ANDX *)iov[0].iov_base;
497 smb_buf = (struct smb_hdr *)iov[0].iov_base;
498
499 if((smb_buf->WordCount != 3) && (smb_buf->WordCount != 4)) {
500 rc = -EIO;
501 cERROR(1,("bad word count %d", smb_buf->WordCount));
502 goto ssetup_exit;
503 }
504 action = le16_to_cpu(pSMB->resp.Action);
505 if (action & GUEST_LOGIN)
Steve French189acaa2006-06-23 02:33:48 +0000506 cFYI(1, ("Guest login")); /* BB mark SesInfo struct? */
Steve French39798772006-05-31 22:40:51 +0000507 ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */
508 cFYI(1, ("UID = %d ", ses->Suid));
509 /* response can have either 3 or 4 word count - Samba sends 3 */
510 /* and lanman response is 3 */
511 bytes_remaining = BCC(smb_buf);
512 bcc_ptr = pByteArea(smb_buf);
513
514 if(smb_buf->WordCount == 4) {
515 __u16 blob_len;
516 blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
517 bcc_ptr += blob_len;
518 if(blob_len > bytes_remaining) {
519 cERROR(1,("bad security blob length %d", blob_len));
520 rc = -EINVAL;
521 goto ssetup_exit;
522 }
523 bytes_remaining -= blob_len;
524 }
525
526 /* BB check if Unicode and decode strings */
527 if(smb_buf->Flags2 & SMBFLG2_UNICODE)
528 rc = decode_unicode_ssetup(&bcc_ptr, bytes_remaining,
529 ses, nls_cp);
530 else
531 rc = decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,nls_cp);
532
533ssetup_exit:
Steve French750d1152006-06-27 06:28:30 +0000534 kfree(str_area);
Steve French39798772006-05-31 22:40:51 +0000535 if(resp_buf_type == CIFS_SMALL_BUFFER) {
536 cFYI(1,("ssetup freeing small buf %p", iov[0].iov_base));
537 cifs_small_buf_release(iov[0].iov_base);
538 } else if(resp_buf_type == CIFS_LARGE_BUFFER)
539 cifs_buf_release(iov[0].iov_base);
540
541 return rc;
542}