]> err.no Git - linux-2.6/blob - fs/cifs/sess.c
[CIFS] Missing include shows up on some architectures
[linux-2.6] / fs / cifs / sess.c
1 /*
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>
32 #include <linux/utsname.h>
33
34 extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
35                        unsigned char *p24);
36
37 extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
38                          unsigned char *p24);
39
40 #ifdef CONFIG_CIFS_EXPERIMENTAL
41
42 static __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
83 void 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
133 void 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
176 int 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
258 int 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
314 int 
315 CIFS_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         
503 ssetup_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 */