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