[CIFS] NTLMv2 support part 5
[pandora-kernel.git] / 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         cFYI(1,("new sess setup"));
328         if(ses == NULL)
329                 return -EINVAL;
330
331         type = ses->server->secType;
332         if(type == LANMAN) {
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 */
339                 return -EOPNOTSUPP;
340 #endif
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 */
346                 wct = 12;
347
348         rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses,
349                             (void **)&smb_buf);
350         if(rc)
351                 return rc;
352
353         pSMB = (SESSION_SETUP_ANDX *)smb_buf;
354
355         capabilities = cifs_ssetup_hdr(ses, pSMB);
356         bcc_ptr = pByteArea(smb_buf);
357
358         if(type == LANMAN) {
359 #ifdef CONFIG_CIFS_WEAK_PW_HASH
360                 char lnm_session_key[CIFS_SESS_KEY_SIZE];
361
362                 /* no capabilities flags in old lanman negotiation */
363
364                 pSMB->old_req.PasswordLength = CIFS_SESS_KEY_SIZE; 
365                 /* BB calculate hash with password */
366                 /* and copy into bcc */
367
368                 calc_lanman_hash(ses, lnm_session_key);
369
370 #ifdef CONFIG_CIFS_DEBUG2
371                 cifs_dump_mem("cryptkey: ",ses->server->cryptKey,
372                         CIFS_SESS_KEY_SIZE);
373 #endif
374                 memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_SESS_KEY_SIZE);
375                 bcc_ptr += CIFS_SESS_KEY_SIZE;
376
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? */
381
382                 cERROR(1,("Negotiating LANMAN setting up strings"));
383                 /* Unicode not allowed for LANMAN dialects */
384                 ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
385 #endif    
386         } else if (type == NTLM) {
387                 char ntlm_session_key[CIFS_SESS_KEY_SIZE];
388
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);
394         
395                 /* calculate session key */
396                 SMBNTencrypt(ses->password, ses->server->cryptKey,
397                              ntlm_session_key);
398
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 */
404
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);
411                 else
412                         ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
413         } else if (type == NTLMv2) {
414                 char * v2_sess_key = 
415                         kmalloc(sizeof(struct ntlmv2_resp), GFP_KERNEL);
416
417                 /* BB FIXME change all users of v2_sess_key to
418                    struct ntlmv2_resp */
419
420                 if(v2_sess_key == NULL) {
421                         cifs_small_buf_release(smb_buf);
422                         return -ENOMEM;
423                 }
424
425                 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
426
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); */
430
431                 pSMB->req_no_secext.CaseSensitivePasswordLength =
432                         cpu_to_le16(sizeof(struct ntlmv2_resp));
433
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); */
440
441                 /* copy session key */
442
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);
447                 kfree(v2_sess_key);
448                 if(ses->capabilities & CAP_UNICODE)
449                         unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
450                 else
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 */
457         }
458
459         count = (long) bcc_ptr - (long) pByteArea(smb_buf);
460         smb_buf->smb_buf_length += count;
461
462         /* if we switch to small buffers, count will need to be fewer
463            than 383 (strings less than 335 bytes) */
464
465         BCC_LE(smb_buf) = cpu_to_le16(count);
466
467
468         /* BB FIXME check for other non ntlm code paths */
469
470         /* BB check is this too big for a small smb? */
471
472         iov[0].iov_base = (char *)pSMB;
473         iov[0].iov_len = smb_buf->smb_buf_length + 4;
474
475         rc = SendReceive2(xid, ses, iov, 1 /* num_iovecs */, &resp_buf_type, 0);
476         /* SMB request buf freed in SendReceive2 */
477
478         cFYI(1,("ssetup rc from sendrecv2 is %d",rc));
479         if(rc)
480                 goto ssetup_exit;
481
482         pSMB = (SESSION_SETUP_ANDX *)iov[0].iov_base;
483         smb_buf = (struct smb_hdr *)iov[0].iov_base;
484
485         if((smb_buf->WordCount != 3) && (smb_buf->WordCount != 4)) {
486                 rc = -EIO;
487                 cERROR(1,("bad word count %d", smb_buf->WordCount));
488                 goto ssetup_exit;
489         }
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);
499
500         if(smb_buf->WordCount == 4) {
501                 __u16 blob_len;
502                 blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
503                 bcc_ptr += blob_len;
504                 if(blob_len > bytes_remaining) {
505                         cERROR(1,("bad security blob length %d", blob_len));
506                         rc = -EINVAL;
507                         goto ssetup_exit;
508                 }
509                 bytes_remaining -= blob_len;
510         }       
511
512         /* BB check if Unicode and decode strings */
513         if(smb_buf->Flags2 & SMBFLG2_UNICODE)
514                 rc = decode_unicode_ssetup(&bcc_ptr, bytes_remaining,
515                                                    ses, nls_cp);
516         else
517                 rc = decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,nls_cp);
518         
519 ssetup_exit:
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);
525
526         return rc;
527 }
528 #endif /* CONFIG_CIFS_EXPERIMENTAL */