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/ctype.h>
33 extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
36 extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
39 #ifdef CONFIG_CIFS_EXPERIMENTAL
41 static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB)
43 __u32 capabilities = 0;
45 /* init fields common to all four types of SessSetup */
46 /* note that header is initialized to zero in header_assemble */
47 pSMB->req.AndXCommand = 0xFF;
48 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
49 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
51 /* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */
53 /* BB verify whether signing required on neg or just on auth frame
56 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
57 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
59 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
60 pSMB->req.hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
62 if (ses->capabilities & CAP_UNICODE) {
63 pSMB->req.hdr.Flags2 |= SMBFLG2_UNICODE;
64 capabilities |= CAP_UNICODE;
66 if (ses->capabilities & CAP_STATUS32) {
67 pSMB->req.hdr.Flags2 |= SMBFLG2_ERR_STATUS;
68 capabilities |= CAP_STATUS32;
70 if (ses->capabilities & CAP_DFS) {
71 pSMB->req.hdr.Flags2 |= SMBFLG2_DFS;
72 capabilities |= CAP_DFS;
74 if (ses->capabilities & CAP_UNIX) {
75 capabilities |= CAP_UNIX;
78 /* BB check whether to init vcnum BB */
82 void unicode_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
83 const struct nls_table * nls_cp)
85 char * bcc_ptr = *pbcc_area;
88 /* BB FIXME add check that strings total less
89 than 335 or will need to send them as arrays */
91 /* align unicode strings, must be word aligned */
92 if ((long) bcc_ptr % 2) {
97 if(ses->userName == NULL) {
98 /* BB what about null user mounts - check that we do this BB */
99 } else { /* 300 should be long enough for any conceivable user name */
100 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->userName,
103 bcc_ptr += 2 * bytes_ret;
104 bcc_ptr += 2; /* account for null termination */
106 if(ses->domainName == NULL)
107 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr,
108 "CIFS_LINUX_DOM", 32, nls_cp);
110 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->domainName,
112 bcc_ptr += 2 * bytes_ret;
113 bcc_ptr += 2; /* account for null terminator */
115 /* Copy OS version */
116 bytes_ret = cifs_strtoUCS((__le16 *)bcc_ptr, "Linux version ", 32,
118 bcc_ptr += 2 * bytes_ret;
119 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release,
121 bcc_ptr += 2 * bytes_ret;
122 bcc_ptr += 2; /* trailing null */
124 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
126 bcc_ptr += 2 * bytes_ret;
127 bcc_ptr += 2; /* trailing null */
129 *pbcc_area = bcc_ptr;
132 void ascii_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
133 const struct nls_table * nls_cp)
135 char * bcc_ptr = *pbcc_area;
138 /* BB what about null user mounts - check that we do this BB */
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);
145 /* BB improve check for overflow */
146 bcc_ptr += strnlen(ses->userName, 200);
148 bcc_ptr++; /* account for null termination */
152 if(ses->domainName == NULL) {
153 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
154 bcc_ptr += 14; /* strlen(CIFS_LINUX_DOM) */
156 strncpy(bcc_ptr, ses->domainName, 256);
157 bcc_ptr += strnlen(ses->domainName, 256);
162 /* BB check for overflow here */
164 strcpy(bcc_ptr, "Linux version ");
165 bcc_ptr += strlen("Linux version ");
166 strcpy(bcc_ptr, system_utsname.release);
167 bcc_ptr += strlen(system_utsname.release) + 1;
169 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
170 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
172 *pbcc_area = bcc_ptr;
175 int decode_unicode_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses,
176 const struct nls_table * nls_cp)
180 char * data = *pbcc_area;
184 cFYI(1,("bleft %d",bleft));
187 /* word align, if bytes remaining is not even */
192 words_left = bleft / 2;
194 /* save off server operating system */
195 len = UniStrnlen((wchar_t *) data, words_left);
197 /* We look for obvious messed up bcc or strings in response so we do not go off
198 the end since (at least) WIN2K and Windows XP have a major bug in not null
199 terminating last Unicode string in response */
200 if(len >= words_left)
204 kfree(ses->serverOS);
205 /* UTF-8 string will not grow more than four times as big as UCS-16 */
206 ses->serverOS = kzalloc(4 * len, GFP_KERNEL);
207 if(ses->serverOS != NULL) {
208 cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len,
211 data += 2 * (len + 1);
212 words_left -= len + 1;
214 /* save off server network operating system */
215 len = UniStrnlen((wchar_t *) data, words_left);
217 if(len >= words_left)
221 kfree(ses->serverNOS);
222 ses->serverNOS = kzalloc(4 * len, GFP_KERNEL); /* BB this is wrong length FIXME BB */
223 if(ses->serverNOS != NULL) {
224 cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len,
226 if(strncmp(ses->serverNOS, "NT LAN Manager 4",16) == 0) {
227 cFYI(1,("NT4 server"));
228 ses->flags |= CIFS_SES_NT4;
231 data += 2 * (len + 1);
232 words_left -= len + 1;
234 /* save off server domain */
235 len = UniStrnlen((wchar_t *) data, words_left);
240 if(ses->serverDomain)
241 kfree(ses->serverDomain);
242 ses->serverDomain = kzalloc(2 * (len + 1), GFP_KERNEL); /* BB FIXME wrong length */
243 if(ses->serverDomain != NULL) {
244 cifs_strfromUCS_le(ses->serverDomain, (__le16 *)data, len,
246 ses->serverDomain[2*len] = 0;
247 ses->serverDomain[(2*len) + 1] = 0;
249 data += 2 * (len + 1);
250 words_left -= len + 1;
252 cFYI(1,("words left: %d",words_left));
257 int decode_ascii_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses,
258 const struct nls_table * nls_cp)
262 char * bcc_ptr = *pbcc_area;
264 cFYI(1,("decode sessetup ascii. bleft %d", bleft));
266 len = strnlen(bcc_ptr, bleft);
271 kfree(ses->serverOS);
273 ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
275 strncpy(ses->serverOS, bcc_ptr, len);
280 len = strnlen(bcc_ptr, bleft);
285 kfree(ses->serverNOS);
287 ses->serverNOS = kzalloc(len + 1, GFP_KERNEL);
289 strncpy(ses->serverNOS, bcc_ptr, len);
294 len = strnlen(bcc_ptr, bleft);
298 if(ses->serverDomain)
299 kfree(ses->serverDomain);
301 ses->serverDomain = kzalloc(len + 1, GFP_KERNEL);
303 strncpy(ses->serverOS, bcc_ptr, len);
308 cFYI(1,("ascii: bytes left %d",bleft));
314 CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
315 const struct nls_table *nls_cp)
320 struct smb_hdr *smb_buf;
322 SESSION_SETUP_ANDX *pSMB;
325 int resp_buf_type = 0;
327 enum securityEnum type;
334 type = ses->server->secType;
336 #ifndef CONFIG_CIFS_WEAK_PW_HASH
337 /* LANMAN and plaintext are less secure and off by default.
338 So we make this explicitly be turned on in kconfig (in the
339 build) and turned on at runtime (changed from the default)
340 in proc/fs/cifs or via mount parm. Unfortunately this is
341 needed for old Win (e.g. Win95), some obscure NAS and OS/2 */
344 wct = 10; /* lanman 2 style sessionsetup */
345 } else if(type == NTLM) /* NTLMv2 may retry NTLM */
346 wct = 13; /* old style NTLM sessionsetup */
347 else /* same size for negotiate or auth, NTLMSSP or extended security */
350 rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses,
355 pSMB = (SESSION_SETUP_ANDX *)smb_buf;
357 capabilities = cifs_ssetup_hdr(ses, pSMB);
358 bcc_ptr = pByteArea(smb_buf);
361 #ifdef CONFIG_CIFS_WEAK_PW_HASH
362 char lnm_session_key[CIFS_SESSION_KEY_SIZE];
363 char password_with_pad[CIFS_ENCPWD_SIZE];
365 /* no capabilities flags in old lanman negotiation */
367 pSMB->old_req.PasswordLength = CIFS_SESSION_KEY_SIZE;
368 /* BB calculate hash with password */
369 /* and copy into bcc */
371 memset(password_with_pad, 0, CIFS_ENCPWD_SIZE);
372 strncpy(password_with_pad, ses->password, CIFS_ENCPWD_SIZE);
374 /* calculate old style session key */
375 /* toupper may be less broken then repeatedly calling
376 nls_toupper would be, but neither handles multibyte code pages
377 but the only alternative would be converting to UCS-16 (Unicode)
378 uppercasing and converting back which is only worth doing if
379 we knew it were utf8. utf8 code page needs its own
380 toupper and tolower and strnicmp functions */
382 for(i = 0; i< CIFS_ENCPWD_SIZE; i++) {
383 password_with_pad[i] = toupper(password_with_pad[i]);
386 SMBencrypt(password_with_pad, ses->server->cryptKey,
389 #ifdef CONFIG_CIFS_DEBUG2
390 cifs_dump_mem("cryptkey: ",ses->server->cryptKey,
391 CIFS_SESSION_KEY_SIZE);
393 /* clear password before we return/free memory */
394 memset(password_with_pad, 0, CIFS_ENCPWD_SIZE);
395 memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_SESSION_KEY_SIZE);
396 bcc_ptr += CIFS_SESSION_KEY_SIZE;
398 /* can not sign if LANMAN negotiated so no need
399 to calculate signing key? but what if server
400 changed to do higher than lanman dialect and
401 we reconnected would we ever calc signing_key? */
403 cERROR(1,("Negotiating LANMAN setting up strings"));
404 /* Unicode not allowed for LANMAN dialects */
405 ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
407 } else if (type == NTLM) {
408 char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
410 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
411 pSMB->req_no_secext.CaseInsensitivePasswordLength =
412 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
413 pSMB->req_no_secext.CaseSensitivePasswordLength =
414 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
416 /* calculate session key */
417 SMBNTencrypt(ses->password, ses->server->cryptKey,
420 if(first_time) /* should this be moved into common code
421 with similar ntlmv2 path? */
422 cifs_calculate_mac_key(
423 ses->server->mac_signing_key,
424 ntlm_session_key, ses->password);
425 /* copy session key */
427 memcpy(bcc_ptr, (char *)ntlm_session_key,CIFS_SESSION_KEY_SIZE);
428 bcc_ptr += CIFS_SESSION_KEY_SIZE;
429 memcpy(bcc_ptr, (char *)ntlm_session_key,CIFS_SESSION_KEY_SIZE);
430 bcc_ptr += CIFS_SESSION_KEY_SIZE;
431 if(ses->capabilities & CAP_UNICODE)
432 unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
434 ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
435 } else /* NTLMSSP or SPNEGO */ {
436 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
437 capabilities |= CAP_EXTENDED_SECURITY;
438 pSMB->req.Capabilities = cpu_to_le32(capabilities);
439 /* BB set password lengths */
442 count = (long) bcc_ptr - (long) pByteArea(smb_buf);
443 smb_buf->smb_buf_length += count;
445 /* if we switch to small buffers, count will need to be fewer
446 than 383 (strings less than 335 bytes) */
448 BCC_LE(smb_buf) = cpu_to_le16(count);
451 /* BB FIXME check for other non ntlm code paths */
453 /* BB check is this too big for a small smb? */
455 iov[0].iov_base = (char *)pSMB;
456 iov[0].iov_len = smb_buf->smb_buf_length + 4;
458 rc = SendReceive2(xid, ses, iov, 1 /* num_iovecs */, &resp_buf_type, 0);
459 /* SMB request buf freed in SendReceive2 */
461 cFYI(1,("ssetup rc from sendrecv2 is %d",rc));
465 pSMB = (SESSION_SETUP_ANDX *)iov[0].iov_base;
466 smb_buf = (struct smb_hdr *)iov[0].iov_base;
468 if((smb_buf->WordCount != 3) && (smb_buf->WordCount != 4)) {
470 cERROR(1,("bad word count %d", smb_buf->WordCount));
473 action = le16_to_cpu(pSMB->resp.Action);
474 if (action & GUEST_LOGIN)
475 cFYI(1, (" Guest login")); /* BB mark SesInfo struct? */
476 ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */
477 cFYI(1, ("UID = %d ", ses->Suid));
478 /* response can have either 3 or 4 word count - Samba sends 3 */
479 /* and lanman response is 3 */
480 bytes_remaining = BCC(smb_buf);
481 bcc_ptr = pByteArea(smb_buf);
483 if(smb_buf->WordCount == 4) {
485 blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
487 if(blob_len > bytes_remaining) {
488 cERROR(1,("bad security blob length %d", blob_len));
492 bytes_remaining -= blob_len;
495 /* BB check if Unicode and decode strings */
496 if(smb_buf->Flags2 & SMBFLG2_UNICODE)
497 rc = decode_unicode_ssetup(&bcc_ptr, bytes_remaining,
500 rc = decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,nls_cp);
503 if(resp_buf_type == CIFS_SMALL_BUFFER) {
504 cFYI(1,("ssetup freeing small buf %p", iov[0].iov_base));
505 cifs_small_buf_release(iov[0].iov_base);
506 } else if(resp_buf_type == CIFS_LARGE_BUFFER)
507 cifs_buf_release(iov[0].iov_base);
511 #endif /* CONFIG_CIFS_EXPERIMENTAL */