4 * SMB/CIFS session setup handling routines
6 * Copyright (c) International Business Machines Corp., 2006
7 * Author(s): Steve French (sfrench@us.ibm.com)
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.
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.
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
26 #include "cifsproto.h"
27 #include "cifs_unicode.h"
28 #include "cifs_debug.h"
31 #include <linux/utsname.h>
33 extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
36 #ifdef CONFIG_CIFS_EXPERIMENTAL
38 static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB)
40 __u32 capabilities = 0;
42 /* init fields common to all four types of SessSetup */
43 /* note that header is initialized to zero in header_assemble */
44 pSMB->req.AndXCommand = 0xFF;
45 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
46 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
48 /* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */
50 /* BB verify whether signing required on neg or just on auth frame
53 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
54 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
56 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
57 pSMB->req.hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
59 if (ses->capabilities & CAP_UNICODE) {
60 pSMB->req.hdr.Flags2 |= SMBFLG2_UNICODE;
61 capabilities |= CAP_UNICODE;
63 if (ses->capabilities & CAP_STATUS32) {
64 pSMB->req.hdr.Flags2 |= SMBFLG2_ERR_STATUS;
65 capabilities |= CAP_STATUS32;
67 if (ses->capabilities & CAP_DFS) {
68 pSMB->req.hdr.Flags2 |= SMBFLG2_DFS;
69 capabilities |= CAP_DFS;
71 if (ses->capabilities & CAP_UNIX) {
72 capabilities |= CAP_UNIX;
75 /* BB check whether to init vcnum BB */
79 static void unicode_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
80 const struct nls_table * nls_cp)
82 char * bcc_ptr = *pbcc_area;
85 /* BB FIXME add check that strings total less
86 than 335 or will need to send them as arrays */
88 /* align unicode strings, must be word aligned */
89 if ((long) bcc_ptr % 2) {
94 if(ses->userName == NULL) {
95 /* BB what about null user mounts - check that we do this BB */
96 } else { /* 300 should be long enough for any conceivable user name */
97 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->userName,
100 bcc_ptr += 2 * bytes_ret;
101 bcc_ptr += 2; /* account for null termination */
103 if(ses->domainName == NULL)
104 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr,
105 "CIFS_LINUX_DOM", 32, nls_cp);
107 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->domainName,
109 bcc_ptr += 2 * bytes_ret;
110 bcc_ptr += 2; /* account for null terminator */
112 /* Copy OS version */
113 bytes_ret = cifs_strtoUCS((__le16 *)bcc_ptr, "Linux version ", 32,
115 bcc_ptr += 2 * bytes_ret;
116 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release,
118 bcc_ptr += 2 * bytes_ret;
119 bcc_ptr += 2; /* trailing null */
121 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
123 bcc_ptr += 2 * bytes_ret;
124 bcc_ptr += 2; /* trailing null */
126 *pbcc_area = bcc_ptr;
129 static void ascii_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
130 const struct nls_table * nls_cp)
132 char * bcc_ptr = *pbcc_area;
135 /* BB what about null user mounts - check that we do this BB */
137 if(ses->userName == NULL) {
138 /* BB what about null user mounts - check that we do this BB */
139 } else { /* 300 should be long enough for any conceivable user name */
140 strncpy(bcc_ptr, ses->userName, 300);
142 /* BB improve check for overflow */
143 bcc_ptr += strnlen(ses->userName, 200);
145 bcc_ptr++; /* account for null termination */
149 if(ses->domainName == NULL) {
150 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
151 bcc_ptr += 14; /* strlen(CIFS_LINUX_DOM) */
153 strncpy(bcc_ptr, ses->domainName, 256);
154 bcc_ptr += strnlen(ses->domainName, 256);
159 /* BB check for overflow here */
161 strcpy(bcc_ptr, "Linux version ");
162 bcc_ptr += strlen("Linux version ");
163 strcpy(bcc_ptr, system_utsname.release);
164 bcc_ptr += strlen(system_utsname.release) + 1;
166 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
167 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
169 *pbcc_area = bcc_ptr;
172 static int decode_unicode_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses,
173 const struct nls_table * nls_cp)
177 char * data = *pbcc_area;
181 cFYI(1,("bleft %d",bleft));
184 /* word align, if bytes remaining is not even */
189 words_left = bleft / 2;
191 /* save off server operating system */
192 len = UniStrnlen((wchar_t *) data, words_left);
194 /* We look for obvious messed up bcc or strings in response so we do not go off
195 the end since (at least) WIN2K and Windows XP have a major bug in not null
196 terminating last Unicode string in response */
197 if(len >= words_left)
201 kfree(ses->serverOS);
202 /* UTF-8 string will not grow more than four times as big as UCS-16 */
203 ses->serverOS = kzalloc(4 * len, GFP_KERNEL);
204 if(ses->serverOS != NULL) {
205 cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len,
208 data += 2 * (len + 1);
209 words_left -= len + 1;
211 /* save off server network operating system */
212 len = UniStrnlen((wchar_t *) data, words_left);
214 if(len >= words_left)
218 kfree(ses->serverNOS);
219 ses->serverNOS = kzalloc(4 * len, GFP_KERNEL); /* BB this is wrong length FIXME BB */
220 if(ses->serverNOS != NULL) {
221 cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len,
223 if(strncmp(ses->serverNOS, "NT LAN Manager 4",16) == 0) {
224 cFYI(1,("NT4 server"));
225 ses->flags |= CIFS_SES_NT4;
228 data += 2 * (len + 1);
229 words_left -= len + 1;
231 /* save off server domain */
232 len = UniStrnlen((wchar_t *) data, words_left);
237 if(ses->serverDomain)
238 kfree(ses->serverDomain);
239 ses->serverDomain = kzalloc(2 * (len + 1), GFP_KERNEL); /* BB FIXME wrong length */
240 if(ses->serverDomain != NULL) {
241 cifs_strfromUCS_le(ses->serverDomain, (__le16 *)data, len,
243 ses->serverDomain[2*len] = 0;
244 ses->serverDomain[(2*len) + 1] = 0;
246 data += 2 * (len + 1);
247 words_left -= len + 1;
249 cFYI(1,("words left: %d",words_left));
254 static int decode_ascii_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses,
255 const struct nls_table * nls_cp)
259 char * bcc_ptr = *pbcc_area;
261 cFYI(1,("decode sessetup ascii. bleft %d", bleft));
263 len = strnlen(bcc_ptr, bleft);
268 kfree(ses->serverOS);
270 ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
272 strncpy(ses->serverOS, bcc_ptr, len);
277 len = strnlen(bcc_ptr, bleft);
282 kfree(ses->serverNOS);
284 ses->serverNOS = kzalloc(len + 1, GFP_KERNEL);
286 strncpy(ses->serverNOS, bcc_ptr, len);
291 len = strnlen(bcc_ptr, bleft);
295 if(ses->serverDomain)
296 kfree(ses->serverDomain);
298 ses->serverDomain = kzalloc(len + 1, GFP_KERNEL);
300 strncpy(ses->serverOS, bcc_ptr, len);
305 cFYI(1,("ascii: bytes left %d",bleft));
311 CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
312 const struct nls_table *nls_cp)
316 struct smb_hdr *smb_buf;
318 SESSION_SETUP_ANDX *pSMB;
321 int resp_buf_type = 0;
323 enum securityEnum type;
327 cFYI(1,("new sess setup"));
331 type = ses->server->secType;
333 #ifndef CONFIG_CIFS_WEAK_PW_HASH
334 /* LANMAN and plaintext are less secure and off by default.
335 So we make this explicitly be turned on in kconfig (in the
336 build) and turned on at runtime (changed from the default)
337 in proc/fs/cifs or via mount parm. Unfortunately this is
338 needed for old Win (e.g. Win95), some obscure NAS and OS/2 */
341 wct = 10; /* lanman 2 style sessionsetup */
342 } else if((type == NTLM) || (type == NTLMv2)) {
343 /* For NTLMv2 failures eventually may need to retry NTLM */
344 wct = 13; /* old style NTLM sessionsetup */
345 } else /* same size for negotiate or auth, NTLMSSP or extended security */
348 rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses,
353 pSMB = (SESSION_SETUP_ANDX *)smb_buf;
355 capabilities = cifs_ssetup_hdr(ses, pSMB);
356 bcc_ptr = pByteArea(smb_buf);
359 #ifdef CONFIG_CIFS_WEAK_PW_HASH
360 char lnm_session_key[CIFS_SESS_KEY_SIZE];
362 /* no capabilities flags in old lanman negotiation */
364 pSMB->old_req.PasswordLength = CIFS_SESS_KEY_SIZE;
365 /* BB calculate hash with password */
366 /* and copy into bcc */
368 calc_lanman_hash(ses, lnm_session_key);
370 #ifdef CONFIG_CIFS_DEBUG2
371 cifs_dump_mem("cryptkey: ",ses->server->cryptKey,
374 memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_SESS_KEY_SIZE);
375 bcc_ptr += CIFS_SESS_KEY_SIZE;
377 /* can not sign if LANMAN negotiated so no need
378 to calculate signing key? but what if server
379 changed to do higher than lanman dialect and
380 we reconnected would we ever calc signing_key? */
382 cERROR(1,("Negotiating LANMAN setting up strings"));
383 /* Unicode not allowed for LANMAN dialects */
384 ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
386 } else if (type == NTLM) {
387 char ntlm_session_key[CIFS_SESS_KEY_SIZE];
389 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
390 pSMB->req_no_secext.CaseInsensitivePasswordLength =
391 cpu_to_le16(CIFS_SESS_KEY_SIZE);
392 pSMB->req_no_secext.CaseSensitivePasswordLength =
393 cpu_to_le16(CIFS_SESS_KEY_SIZE);
395 /* calculate session key */
396 SMBNTencrypt(ses->password, ses->server->cryptKey,
399 if(first_time) /* should this be moved into common code
400 with similar ntlmv2 path? */
401 cifs_calculate_mac_key( ses->server->mac_signing_key,
402 ntlm_session_key, ses->password);
403 /* copy session key */
405 memcpy(bcc_ptr, (char *)ntlm_session_key,CIFS_SESS_KEY_SIZE);
406 bcc_ptr += CIFS_SESS_KEY_SIZE;
407 memcpy(bcc_ptr, (char *)ntlm_session_key,CIFS_SESS_KEY_SIZE);
408 bcc_ptr += CIFS_SESS_KEY_SIZE;
409 if(ses->capabilities & CAP_UNICODE)
410 unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
412 ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
413 } else if (type == NTLMv2) {
415 kmalloc(sizeof(struct ntlmv2_resp), GFP_KERNEL);
417 /* BB FIXME change all users of v2_sess_key to
418 struct ntlmv2_resp */
420 if(v2_sess_key == NULL) {
421 cifs_small_buf_release(smb_buf);
425 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
427 /* LM2 password would be here if we supported it */
428 pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
429 /* cpu_to_le16(LM2_SESS_KEY_SIZE); */
431 pSMB->req_no_secext.CaseSensitivePasswordLength =
432 cpu_to_le16(sizeof(struct ntlmv2_resp));
434 /* calculate session key */
435 setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp);
436 if(first_time) /* should this be moved into common code
437 with similar ntlmv2 path? */
438 /* cifs_calculate_ntlmv2_mac_key(ses->server->mac_signing_key,
439 response BB FIXME, v2_sess_key); */
441 /* copy session key */
443 /* memcpy(bcc_ptr, (char *)ntlm_session_key,LM2_SESS_KEY_SIZE);
444 bcc_ptr += LM2_SESS_KEY_SIZE; */
445 memcpy(bcc_ptr, (char *)v2_sess_key, sizeof(struct ntlmv2_resp));
446 bcc_ptr += sizeof(struct ntlmv2_resp);
448 if(ses->capabilities & CAP_UNICODE)
449 unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
451 ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
452 } else /* NTLMSSP or SPNEGO */ {
453 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
454 capabilities |= CAP_EXTENDED_SECURITY;
455 pSMB->req.Capabilities = cpu_to_le32(capabilities);
456 /* BB set password lengths */
459 count = (long) bcc_ptr - (long) pByteArea(smb_buf);
460 smb_buf->smb_buf_length += count;
462 /* if we switch to small buffers, count will need to be fewer
463 than 383 (strings less than 335 bytes) */
465 BCC_LE(smb_buf) = cpu_to_le16(count);
468 /* BB FIXME check for other non ntlm code paths */
470 /* BB check is this too big for a small smb? */
472 iov[0].iov_base = (char *)pSMB;
473 iov[0].iov_len = smb_buf->smb_buf_length + 4;
475 rc = SendReceive2(xid, ses, iov, 1 /* num_iovecs */, &resp_buf_type, 0);
476 /* SMB request buf freed in SendReceive2 */
478 cFYI(1,("ssetup rc from sendrecv2 is %d",rc));
482 pSMB = (SESSION_SETUP_ANDX *)iov[0].iov_base;
483 smb_buf = (struct smb_hdr *)iov[0].iov_base;
485 if((smb_buf->WordCount != 3) && (smb_buf->WordCount != 4)) {
487 cERROR(1,("bad word count %d", smb_buf->WordCount));
490 action = le16_to_cpu(pSMB->resp.Action);
491 if (action & GUEST_LOGIN)
492 cFYI(1, (" Guest login")); /* BB mark SesInfo struct? */
493 ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */
494 cFYI(1, ("UID = %d ", ses->Suid));
495 /* response can have either 3 or 4 word count - Samba sends 3 */
496 /* and lanman response is 3 */
497 bytes_remaining = BCC(smb_buf);
498 bcc_ptr = pByteArea(smb_buf);
500 if(smb_buf->WordCount == 4) {
502 blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
504 if(blob_len > bytes_remaining) {
505 cERROR(1,("bad security blob length %d", blob_len));
509 bytes_remaining -= blob_len;
512 /* BB check if Unicode and decode strings */
513 if(smb_buf->Flags2 & SMBFLG2_UNICODE)
514 rc = decode_unicode_ssetup(&bcc_ptr, bytes_remaining,
517 rc = decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,nls_cp);
520 if(resp_buf_type == CIFS_SMALL_BUFFER) {
521 cFYI(1,("ssetup freeing small buf %p", iov[0].iov_base));
522 cifs_small_buf_release(iov[0].iov_base);
523 } else if(resp_buf_type == CIFS_LARGE_BUFFER)
524 cifs_buf_release(iov[0].iov_base);
528 #endif /* CONFIG_CIFS_EXPERIMENTAL */