[CIFS] Support for setting up SMB sessions to legacy lanman servers
[safe/jmp/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
33 extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
34                        unsigned char *p24);
35
36 extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
37                          unsigned char *p24);
38
39 #ifdef CONFIG_CIFS_EXPERIMENTAL
40
41 static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB)
42 {
43         __u32 capabilities = 0;
44
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);
50
51         /* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */
52
53         /* BB verify whether signing required on neg or just on auth frame 
54            (and NTLM case) */
55
56         capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
57                         CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
58
59         if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
60                 pSMB->req.hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
61
62         if (ses->capabilities & CAP_UNICODE) {
63                 pSMB->req.hdr.Flags2 |= SMBFLG2_UNICODE;
64                 capabilities |= CAP_UNICODE;
65         }
66         if (ses->capabilities & CAP_STATUS32) {
67                 pSMB->req.hdr.Flags2 |= SMBFLG2_ERR_STATUS;
68                 capabilities |= CAP_STATUS32;
69         }
70         if (ses->capabilities & CAP_DFS) {
71                 pSMB->req.hdr.Flags2 |= SMBFLG2_DFS;
72                 capabilities |= CAP_DFS;
73         }
74         if (ses->capabilities & CAP_UNIX) {
75                 capabilities |= CAP_UNIX;
76         }
77
78         /* BB check whether to init vcnum BB */
79         return capabilities;
80 }
81
82 void unicode_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
83                             const struct nls_table * nls_cp)
84 {
85         char * bcc_ptr = *pbcc_area;
86         int bytes_ret = 0;
87
88         /* BB FIXME add check that strings total less
89         than 335 or will need to send them as arrays */
90
91         /* align unicode strings, must be word aligned */
92         if ((long) bcc_ptr % 2) {
93                 *bcc_ptr = 0;
94                 bcc_ptr++;
95         }
96         /* copy user */
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,
101                                           300, nls_cp);
102         }
103         bcc_ptr += 2 * bytes_ret;
104         bcc_ptr += 2; /* account for null termination */
105         /* copy domain */
106         if(ses->domainName == NULL)
107                 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr,
108                                           "CIFS_LINUX_DOM", 32, nls_cp);
109         else
110                 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;
119         bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release,
120                                   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
132 void ascii_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
133                           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 */
146         bcc_ptr += strnlen(ses->userName, 200);
147         *bcc_ptr = 0;
148         bcc_ptr++; /* account for null termination */
149
150         /* copy domain */
151         
152         if(ses->domainName == NULL) {
153                 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
154                 bcc_ptr += 14;  /* strlen(CIFS_LINUX_DOM) */
155         } else {
156                 strncpy(bcc_ptr, ses->domainName, 256); 
157                 bcc_ptr += strnlen(ses->domainName, 256);
158         }
159         *bcc_ptr = 0;
160         bcc_ptr++;
161
162         /* BB check for overflow here */
163
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;
168
169         strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
170         bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
171
172         *pbcc_area = bcc_ptr;
173 }
174
175 int decode_unicode_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses,
176                             const struct nls_table * nls_cp)
177 {
178         int rc = 0;
179         int words_left, len;
180         char * data = *pbcc_area;
181
182
183
184         cFYI(1,("bleft %d",bleft));
185
186
187         /* word align, if bytes remaining is not even */
188         if(bleft % 2) {
189                 bleft--;
190                 data++;
191         }
192         words_left = bleft / 2;
193
194         /* save off server operating system */
195         len = UniStrnlen((wchar_t *) data, words_left);
196
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)
201                 return rc;
202
203         if(ses->serverOS)
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,
209                                    nls_cp);
210         }
211         data += 2 * (len + 1);
212         words_left -= len + 1;
213
214         /* save off server network operating system */
215         len = UniStrnlen((wchar_t *) data, words_left);
216
217         if(len >= words_left)
218                 return rc;
219
220         if(ses->serverNOS)
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,
225                                    nls_cp);
226                 if(strncmp(ses->serverNOS, "NT LAN Manager 4",16) == 0) {
227                         cFYI(1,("NT4 server"));
228                         ses->flags |= CIFS_SES_NT4;
229                 }
230         }
231         data += 2 * (len + 1);
232         words_left -= len + 1;
233
234         /* save off server domain */
235         len = UniStrnlen((wchar_t *) data, words_left);
236
237         if(len > words_left)
238                 return rc;
239
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,
245                                    nls_cp);
246                 ses->serverDomain[2*len] = 0;
247                 ses->serverDomain[(2*len) + 1] = 0;
248         }
249         data += 2 * (len + 1);
250         words_left -= len + 1;
251         
252         cFYI(1,("words left: %d",words_left));
253
254         return rc;
255 }
256
257 int decode_ascii_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses,
258                             const struct nls_table * nls_cp)
259 {
260         int rc = 0;
261         int len;
262         char * bcc_ptr = *pbcc_area;
263
264         cFYI(1,("decode sessetup ascii. bleft %d", bleft));
265         
266         len = strnlen(bcc_ptr, bleft);
267         if(len >= bleft)
268                 return rc;
269         
270         if(ses->serverOS)
271                 kfree(ses->serverOS);
272
273         ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
274         if(ses->serverOS)
275                 strncpy(ses->serverOS, bcc_ptr, len);
276
277         bcc_ptr += len + 1;
278         bleft -= len + 1;
279
280         len = strnlen(bcc_ptr, bleft);
281         if(len >= bleft)
282                 return rc;
283
284         if(ses->serverNOS)
285                 kfree(ses->serverNOS);
286
287         ses->serverNOS = kzalloc(len + 1, GFP_KERNEL);
288         if(ses->serverNOS)
289                 strncpy(ses->serverNOS, bcc_ptr, len);
290
291         bcc_ptr += len + 1;
292         bleft -= len + 1;
293
294         len = strnlen(bcc_ptr, bleft);
295         if(len > bleft)
296                 return rc;
297
298         if(ses->serverDomain)
299                 kfree(ses->serverDomain);
300
301         ses->serverDomain = kzalloc(len + 1, GFP_KERNEL);
302         if(ses->serverOS)
303                 strncpy(ses->serverOS, bcc_ptr, len);
304
305         bcc_ptr += len + 1;
306         bleft -= len + 1;
307
308         cFYI(1,("ascii: bytes left %d",bleft));
309
310         return rc;
311 }
312
313 int 
314 CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
315                 const struct nls_table *nls_cp)
316 {
317         int rc = 0;
318         int wct;
319         int i;
320         struct smb_hdr *smb_buf;
321         char *bcc_ptr;
322         SESSION_SETUP_ANDX *pSMB;
323         __u32 capabilities;
324         int count;
325         int resp_buf_type = 0;
326         struct kvec iov[1];
327         enum securityEnum type;
328         __u16 action;
329         int bytes_remaining;
330         
331         if(ses == NULL)
332                 return -EINVAL;
333
334         type = ses->server->secType;
335         if(type == LANMAN) {
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 */
342                 return -EOPNOTSUPP;
343 #endif
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 */
348                 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);
358         bcc_ptr = pByteArea(smb_buf);
359
360         if(type == LANMAN) {
361 #ifdef CONFIG_CIFS_WEAK_PW_HASH
362                 char lnm_session_key[CIFS_SESSION_KEY_SIZE];
363                 char password_with_pad[CIFS_ENCPWD_SIZE];
364
365                 /* no capabilities flags in old lanman negotiation */
366
367                 pSMB->old_req.PasswordLength = CIFS_SESSION_KEY_SIZE; 
368                 /* BB calculate hash with password */
369                 /* and copy into bcc */
370
371                 memset(password_with_pad, 0, CIFS_ENCPWD_SIZE);
372                 strncpy(password_with_pad, ses->password, CIFS_ENCPWD_SIZE);
373
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 */
381                 
382                 for(i = 0; i< CIFS_ENCPWD_SIZE; i++) {
383                         password_with_pad[i] = toupper(password_with_pad[i]);
384                 }
385
386                 SMBencrypt(password_with_pad, ses->server->cryptKey,
387                            lnm_session_key);
388
389 #ifdef CONFIG_CIFS_DEBUG2
390                 cifs_dump_mem("cryptkey: ",ses->server->cryptKey,
391                         CIFS_SESSION_KEY_SIZE);
392 #endif
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;
397
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? */
402
403                 cERROR(1,("Negotiating LANMAN setting up strings"));
404                 /* Unicode not allowed for LANMAN dialects */
405                 ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
406 #endif    
407         } else if (type == NTLM) {
408                 char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
409
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);
415         
416                 /* calculate session key */
417                 SMBNTencrypt(ses->password, ses->server->cryptKey,
418                              ntlm_session_key);
419
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 */
426
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);
433                 else
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 */
440         }
441
442         count = (long) bcc_ptr - (long) pByteArea(smb_buf);
443         smb_buf->smb_buf_length += count;
444
445         /* if we switch to small buffers, count will need to be fewer
446            than 383 (strings less than 335 bytes) */
447
448         BCC_LE(smb_buf) = cpu_to_le16(count);
449
450
451         /* BB FIXME check for other non ntlm code paths */
452
453         /* BB check is this too big for a small smb? */
454
455         iov[0].iov_base = (char *)pSMB;
456         iov[0].iov_len = smb_buf->smb_buf_length + 4;
457
458         rc = SendReceive2(xid, ses, iov, 1 /* num_iovecs */, &resp_buf_type, 0);
459         /* SMB request buf freed in SendReceive2 */
460
461         cFYI(1,("ssetup rc from sendrecv2 is %d",rc));
462         if(rc)
463                 goto ssetup_exit;
464
465         pSMB = (SESSION_SETUP_ANDX *)iov[0].iov_base;
466         smb_buf = (struct smb_hdr *)iov[0].iov_base;
467
468         if((smb_buf->WordCount != 3) && (smb_buf->WordCount != 4)) {
469                 rc = -EIO;
470                 cERROR(1,("bad word count %d", smb_buf->WordCount));
471                 goto ssetup_exit;
472         }
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);
482
483         if(smb_buf->WordCount == 4) {
484                 __u16 blob_len;
485                 blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
486                 bcc_ptr += blob_len;
487                 if(blob_len > bytes_remaining) {
488                         cERROR(1,("bad security blob length %d", blob_len));
489                         rc = -EINVAL;
490                         goto ssetup_exit;
491                 }
492                 bytes_remaining -= blob_len;
493         }       
494
495         /* BB check if Unicode and decode strings */
496         if(smb_buf->Flags2 & SMBFLG2_UNICODE)
497                 rc = decode_unicode_ssetup(&bcc_ptr, bytes_remaining,
498                                                    ses, nls_cp);
499         else
500                 rc = decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,nls_cp);
501         
502 ssetup_exit:
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);
508
509         return rc;
510 }
511 #endif /* CONFIG_CIFS_EXPERIMENTAL */