blob: fdc248fffa0aa170d3f2fa2e9ebb2ad44f22b727 [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"
31#include <linux/ctype.h>
Steve French9c535882006-06-01 05:09:10 +000032#include <linux/utsname.h>
Steve French39798772006-05-31 22:40:51 +000033
34extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
35 unsigned char *p24);
36
37extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
38 unsigned char *p24);
39
40#ifdef CONFIG_CIFS_EXPERIMENTAL
41
42static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB)
43{
44 __u32 capabilities = 0;
45
46 /* init fields common to all four types of SessSetup */
47 /* note that header is initialized to zero in header_assemble */
48 pSMB->req.AndXCommand = 0xFF;
49 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
50 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
51
52 /* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */
53
54 /* BB verify whether signing required on neg or just on auth frame
55 (and NTLM case) */
56
57 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
58 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
59
60 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
61 pSMB->req.hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
62
63 if (ses->capabilities & CAP_UNICODE) {
64 pSMB->req.hdr.Flags2 |= SMBFLG2_UNICODE;
65 capabilities |= CAP_UNICODE;
66 }
67 if (ses->capabilities & CAP_STATUS32) {
68 pSMB->req.hdr.Flags2 |= SMBFLG2_ERR_STATUS;
69 capabilities |= CAP_STATUS32;
70 }
71 if (ses->capabilities & CAP_DFS) {
72 pSMB->req.hdr.Flags2 |= SMBFLG2_DFS;
73 capabilities |= CAP_DFS;
74 }
75 if (ses->capabilities & CAP_UNIX) {
76 capabilities |= CAP_UNIX;
77 }
78
79 /* BB check whether to init vcnum BB */
80 return capabilities;
81}
82
83void unicode_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
84 const struct nls_table * nls_cp)
85{
86 char * bcc_ptr = *pbcc_area;
87 int bytes_ret = 0;
88
89 /* BB FIXME add check that strings total less
90 than 335 or will need to send them as arrays */
91
92 /* align unicode strings, must be word aligned */
93 if ((long) bcc_ptr % 2) {
94 *bcc_ptr = 0;
95 bcc_ptr++;
96 }
97 /* copy user */
98 if(ses->userName == NULL) {
99 /* BB what about null user mounts - check that we do this BB */
100 } else { /* 300 should be long enough for any conceivable user name */
101 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->userName,
102 300, nls_cp);
103 }
104 bcc_ptr += 2 * bytes_ret;
105 bcc_ptr += 2; /* account for null termination */
106 /* copy domain */
107 if(ses->domainName == NULL)
108 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr,
109 "CIFS_LINUX_DOM", 32, nls_cp);
110 else
111 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->domainName,
112 256, nls_cp);
113 bcc_ptr += 2 * bytes_ret;
114 bcc_ptr += 2; /* account for null terminator */
115
116 /* Copy OS version */
117 bytes_ret = cifs_strtoUCS((__le16 *)bcc_ptr, "Linux version ", 32,
118 nls_cp);
119 bcc_ptr += 2 * bytes_ret;
120 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release,
121 32, nls_cp);
122 bcc_ptr += 2 * bytes_ret;
123 bcc_ptr += 2; /* trailing null */
124
125 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
126 32, nls_cp);
127 bcc_ptr += 2 * bytes_ret;
128 bcc_ptr += 2; /* trailing null */
129
130 *pbcc_area = bcc_ptr;
131}
132
133void ascii_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
134 const struct nls_table * nls_cp)
135{
136 char * bcc_ptr = *pbcc_area;
137
138 /* copy user */
139 /* BB what about null user mounts - check that we do this BB */
140 /* copy user */
141 if(ses->userName == NULL) {
142 /* BB what about null user mounts - check that we do this BB */
143 } else { /* 300 should be long enough for any conceivable user name */
144 strncpy(bcc_ptr, ses->userName, 300);
145 }
146 /* BB improve check for overflow */
147 bcc_ptr += strnlen(ses->userName, 200);
148 *bcc_ptr = 0;
149 bcc_ptr++; /* account for null termination */
150
151 /* copy domain */
152
153 if(ses->domainName == NULL) {
154 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
155 bcc_ptr += 14; /* strlen(CIFS_LINUX_DOM) */
156 } else {
157 strncpy(bcc_ptr, ses->domainName, 256);
158 bcc_ptr += strnlen(ses->domainName, 256);
159 }
160 *bcc_ptr = 0;
161 bcc_ptr++;
162
163 /* BB check for overflow here */
164
165 strcpy(bcc_ptr, "Linux version ");
166 bcc_ptr += strlen("Linux version ");
167 strcpy(bcc_ptr, system_utsname.release);
168 bcc_ptr += strlen(system_utsname.release) + 1;
169
170 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
171 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
172
173 *pbcc_area = bcc_ptr;
174}
175
176int decode_unicode_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses,
177 const struct nls_table * nls_cp)
178{
179 int rc = 0;
180 int words_left, len;
181 char * data = *pbcc_area;
182
183
184
185 cFYI(1,("bleft %d",bleft));
186
187
188 /* word align, if bytes remaining is not even */
189 if(bleft % 2) {
190 bleft--;
191 data++;
192 }
193 words_left = bleft / 2;
194
195 /* save off server operating system */
196 len = UniStrnlen((wchar_t *) data, words_left);
197
198/* We look for obvious messed up bcc or strings in response so we do not go off
199 the end since (at least) WIN2K and Windows XP have a major bug in not null
200 terminating last Unicode string in response */
201 if(len >= words_left)
202 return rc;
203
204 if(ses->serverOS)
205 kfree(ses->serverOS);
206 /* UTF-8 string will not grow more than four times as big as UCS-16 */
207 ses->serverOS = kzalloc(4 * len, GFP_KERNEL);
208 if(ses->serverOS != NULL) {
209 cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len,
210 nls_cp);
211 }
212 data += 2 * (len + 1);
213 words_left -= len + 1;
214
215 /* save off server network operating system */
216 len = UniStrnlen((wchar_t *) data, words_left);
217
218 if(len >= words_left)
219 return rc;
220
221 if(ses->serverNOS)
222 kfree(ses->serverNOS);
223 ses->serverNOS = kzalloc(4 * len, GFP_KERNEL); /* BB this is wrong length FIXME BB */
224 if(ses->serverNOS != NULL) {
225 cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len,
226 nls_cp);
227 if(strncmp(ses->serverNOS, "NT LAN Manager 4",16) == 0) {
228 cFYI(1,("NT4 server"));
229 ses->flags |= CIFS_SES_NT4;
230 }
231 }
232 data += 2 * (len + 1);
233 words_left -= len + 1;
234
235 /* save off server domain */
236 len = UniStrnlen((wchar_t *) data, words_left);
237
238 if(len > words_left)
239 return rc;
240
241 if(ses->serverDomain)
242 kfree(ses->serverDomain);
243 ses->serverDomain = kzalloc(2 * (len + 1), GFP_KERNEL); /* BB FIXME wrong length */
244 if(ses->serverDomain != NULL) {
245 cifs_strfromUCS_le(ses->serverDomain, (__le16 *)data, len,
246 nls_cp);
247 ses->serverDomain[2*len] = 0;
248 ses->serverDomain[(2*len) + 1] = 0;
249 }
250 data += 2 * (len + 1);
251 words_left -= len + 1;
252
253 cFYI(1,("words left: %d",words_left));
254
255 return rc;
256}
257
258int decode_ascii_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses,
259 const struct nls_table * nls_cp)
260{
261 int rc = 0;
262 int len;
263 char * bcc_ptr = *pbcc_area;
264
265 cFYI(1,("decode sessetup ascii. bleft %d", bleft));
266
267 len = strnlen(bcc_ptr, bleft);
268 if(len >= bleft)
269 return rc;
270
271 if(ses->serverOS)
272 kfree(ses->serverOS);
273
274 ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
275 if(ses->serverOS)
276 strncpy(ses->serverOS, bcc_ptr, len);
277
278 bcc_ptr += len + 1;
279 bleft -= len + 1;
280
281 len = strnlen(bcc_ptr, bleft);
282 if(len >= bleft)
283 return rc;
284
285 if(ses->serverNOS)
286 kfree(ses->serverNOS);
287
288 ses->serverNOS = kzalloc(len + 1, GFP_KERNEL);
289 if(ses->serverNOS)
290 strncpy(ses->serverNOS, bcc_ptr, len);
291
292 bcc_ptr += len + 1;
293 bleft -= len + 1;
294
295 len = strnlen(bcc_ptr, bleft);
296 if(len > bleft)
297 return rc;
298
299 if(ses->serverDomain)
300 kfree(ses->serverDomain);
301
302 ses->serverDomain = kzalloc(len + 1, GFP_KERNEL);
303 if(ses->serverOS)
304 strncpy(ses->serverOS, bcc_ptr, len);
305
306 bcc_ptr += len + 1;
307 bleft -= len + 1;
308
309 cFYI(1,("ascii: bytes left %d",bleft));
310
311 return rc;
312}
313
314int
315CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
316 const struct nls_table *nls_cp)
317{
318 int rc = 0;
319 int wct;
320 int i;
321 struct smb_hdr *smb_buf;
322 char *bcc_ptr;
323 SESSION_SETUP_ANDX *pSMB;
324 __u32 capabilities;
325 int count;
326 int resp_buf_type = 0;
327 struct kvec iov[1];
328 enum securityEnum type;
329 __u16 action;
330 int bytes_remaining;
331
332 if(ses == NULL)
333 return -EINVAL;
334
335 type = ses->server->secType;
336 if(type == LANMAN) {
337#ifndef CONFIG_CIFS_WEAK_PW_HASH
338 /* LANMAN and plaintext are less secure and off by default.
339 So we make this explicitly be turned on in kconfig (in the
340 build) and turned on at runtime (changed from the default)
341 in proc/fs/cifs or via mount parm. Unfortunately this is
342 needed for old Win (e.g. Win95), some obscure NAS and OS/2 */
343 return -EOPNOTSUPP;
344#endif
345 wct = 10; /* lanman 2 style sessionsetup */
346 } else if(type == NTLM) /* NTLMv2 may retry NTLM */
347 wct = 13; /* old style NTLM sessionsetup */
348 else /* same size for negotiate or auth, NTLMSSP or extended security */
349 wct = 12;
350
351 rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses,
352 (void **)&smb_buf);
353 if(rc)
354 return rc;
355
356 pSMB = (SESSION_SETUP_ANDX *)smb_buf;
357
358 capabilities = cifs_ssetup_hdr(ses, pSMB);
359 bcc_ptr = pByteArea(smb_buf);
360
361 if(type == LANMAN) {
362#ifdef CONFIG_CIFS_WEAK_PW_HASH
363 char lnm_session_key[CIFS_SESSION_KEY_SIZE];
364 char password_with_pad[CIFS_ENCPWD_SIZE];
365
366 /* no capabilities flags in old lanman negotiation */
367
368 pSMB->old_req.PasswordLength = CIFS_SESSION_KEY_SIZE;
369 /* BB calculate hash with password */
370 /* and copy into bcc */
371
372 memset(password_with_pad, 0, CIFS_ENCPWD_SIZE);
373 strncpy(password_with_pad, ses->password, CIFS_ENCPWD_SIZE);
374
375 /* calculate old style session key */
376 /* toupper may be less broken then repeatedly calling
377 nls_toupper would be, but neither handles multibyte code pages
378 but the only alternative would be converting to UCS-16 (Unicode)
379 uppercasing and converting back which is only worth doing if
380 we knew it were utf8. utf8 code page needs its own
381 toupper and tolower and strnicmp functions */
382
383 for(i = 0; i< CIFS_ENCPWD_SIZE; i++) {
384 password_with_pad[i] = toupper(password_with_pad[i]);
385 }
386
387 SMBencrypt(password_with_pad, ses->server->cryptKey,
388 lnm_session_key);
389
390#ifdef CONFIG_CIFS_DEBUG2
391 cifs_dump_mem("cryptkey: ",ses->server->cryptKey,
392 CIFS_SESSION_KEY_SIZE);
393#endif
394 /* clear password before we return/free memory */
395 memset(password_with_pad, 0, CIFS_ENCPWD_SIZE);
396 memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_SESSION_KEY_SIZE);
397 bcc_ptr += CIFS_SESSION_KEY_SIZE;
398
399 /* can not sign if LANMAN negotiated so no need
400 to calculate signing key? but what if server
401 changed to do higher than lanman dialect and
402 we reconnected would we ever calc signing_key? */
403
404 cERROR(1,("Negotiating LANMAN setting up strings"));
405 /* Unicode not allowed for LANMAN dialects */
406 ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
407#endif
408 } else if (type == NTLM) {
409 char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
410
411 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
412 pSMB->req_no_secext.CaseInsensitivePasswordLength =
413 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
414 pSMB->req_no_secext.CaseSensitivePasswordLength =
415 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
416
417 /* calculate session key */
418 SMBNTencrypt(ses->password, ses->server->cryptKey,
419 ntlm_session_key);
420
421 if(first_time) /* should this be moved into common code
422 with similar ntlmv2 path? */
423 cifs_calculate_mac_key(
424 ses->server->mac_signing_key,
425 ntlm_session_key, ses->password);
426 /* copy session key */
427
428 memcpy(bcc_ptr, (char *)ntlm_session_key,CIFS_SESSION_KEY_SIZE);
429 bcc_ptr += CIFS_SESSION_KEY_SIZE;
430 memcpy(bcc_ptr, (char *)ntlm_session_key,CIFS_SESSION_KEY_SIZE);
431 bcc_ptr += CIFS_SESSION_KEY_SIZE;
432 if(ses->capabilities & CAP_UNICODE)
433 unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
434 else
435 ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
436 } else /* NTLMSSP or SPNEGO */ {
437 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
438 capabilities |= CAP_EXTENDED_SECURITY;
439 pSMB->req.Capabilities = cpu_to_le32(capabilities);
440 /* BB set password lengths */
441 }
442
443 count = (long) bcc_ptr - (long) pByteArea(smb_buf);
444 smb_buf->smb_buf_length += count;
445
446 /* if we switch to small buffers, count will need to be fewer
447 than 383 (strings less than 335 bytes) */
448
449 BCC_LE(smb_buf) = cpu_to_le16(count);
450
451
452 /* BB FIXME check for other non ntlm code paths */
453
454 /* BB check is this too big for a small smb? */
455
456 iov[0].iov_base = (char *)pSMB;
457 iov[0].iov_len = smb_buf->smb_buf_length + 4;
458
459 rc = SendReceive2(xid, ses, iov, 1 /* num_iovecs */, &resp_buf_type, 0);
460 /* SMB request buf freed in SendReceive2 */
461
462 cFYI(1,("ssetup rc from sendrecv2 is %d",rc));
463 if(rc)
464 goto ssetup_exit;
465
466 pSMB = (SESSION_SETUP_ANDX *)iov[0].iov_base;
467 smb_buf = (struct smb_hdr *)iov[0].iov_base;
468
469 if((smb_buf->WordCount != 3) && (smb_buf->WordCount != 4)) {
470 rc = -EIO;
471 cERROR(1,("bad word count %d", smb_buf->WordCount));
472 goto ssetup_exit;
473 }
474 action = le16_to_cpu(pSMB->resp.Action);
475 if (action & GUEST_LOGIN)
476 cFYI(1, (" Guest login")); /* BB mark SesInfo struct? */
477 ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */
478 cFYI(1, ("UID = %d ", ses->Suid));
479 /* response can have either 3 or 4 word count - Samba sends 3 */
480 /* and lanman response is 3 */
481 bytes_remaining = BCC(smb_buf);
482 bcc_ptr = pByteArea(smb_buf);
483
484 if(smb_buf->WordCount == 4) {
485 __u16 blob_len;
486 blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
487 bcc_ptr += blob_len;
488 if(blob_len > bytes_remaining) {
489 cERROR(1,("bad security blob length %d", blob_len));
490 rc = -EINVAL;
491 goto ssetup_exit;
492 }
493 bytes_remaining -= blob_len;
494 }
495
496 /* BB check if Unicode and decode strings */
497 if(smb_buf->Flags2 & SMBFLG2_UNICODE)
498 rc = decode_unicode_ssetup(&bcc_ptr, bytes_remaining,
499 ses, nls_cp);
500 else
501 rc = decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,nls_cp);
502
503ssetup_exit:
504 if(resp_buf_type == CIFS_SMALL_BUFFER) {
505 cFYI(1,("ssetup freeing small buf %p", iov[0].iov_base));
506 cifs_small_buf_release(iov[0].iov_base);
507 } else if(resp_buf_type == CIFS_LARGE_BUFFER)
508 cifs_buf_release(iov[0].iov_base);
509
510 return rc;
511}
512#endif /* CONFIG_CIFS_EXPERIMENTAL */