Merge git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable
[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, 2007
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 #include "cifs_spnego.h"
33
34 extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
35                          unsigned char *p24);
36
37 /* Checks if this is the first smb session to be reconnected after
38    the socket has been reestablished (so we know whether to use vc 0).
39    Called while holding the cifs_tcp_ses_lock, so do not block */
40 static bool is_first_ses_reconnect(struct cifsSesInfo *ses)
41 {
42         struct list_head *tmp;
43         struct cifsSesInfo *tmp_ses;
44
45         list_for_each(tmp, &ses->server->smb_ses_list) {
46                 tmp_ses = list_entry(tmp, struct cifsSesInfo,
47                                      smb_ses_list);
48                 if (tmp_ses->need_reconnect == false)
49                         return false;
50         }
51         /* could not find a session that was already connected,
52            this must be the first one we are reconnecting */
53         return true;
54 }
55
56 /*
57  *      vc number 0 is treated specially by some servers, and should be the
58  *      first one we request.  After that we can use vcnumbers up to maxvcs,
59  *      one for each smb session (some Windows versions set maxvcs incorrectly
60  *      so maxvc=1 can be ignored).  If we have too many vcs, we can reuse
61  *      any vc but zero (some servers reset the connection on vcnum zero)
62  *
63  */
64 static __le16 get_next_vcnum(struct cifsSesInfo *ses)
65 {
66         __u16 vcnum = 0;
67         struct list_head *tmp;
68         struct cifsSesInfo *tmp_ses;
69         __u16 max_vcs = ses->server->max_vcs;
70         __u16 i;
71         int free_vc_found = 0;
72
73         /* Quoting the MS-SMB specification: "Windows-based SMB servers set this
74         field to one but do not enforce this limit, which allows an SMB client
75         to establish more virtual circuits than allowed by this value ... but
76         other server implementations can enforce this limit." */
77         if (max_vcs < 2)
78                 max_vcs = 0xFFFF;
79
80         write_lock(&cifs_tcp_ses_lock);
81         if ((ses->need_reconnect) && is_first_ses_reconnect(ses))
82                         goto get_vc_num_exit;  /* vcnum will be zero */
83         for (i = ses->server->srv_count - 1; i < max_vcs; i++) {
84                 if (i == 0) /* this is the only connection, use vc 0 */
85                         break;
86
87                 free_vc_found = 1;
88
89                 list_for_each(tmp, &ses->server->smb_ses_list) {
90                         tmp_ses = list_entry(tmp, struct cifsSesInfo,
91                                              smb_ses_list);
92                         if (tmp_ses->vcnum == i) {
93                                 free_vc_found = 0;
94                                 break; /* found duplicate, try next vcnum */
95                         }
96                 }
97                 if (free_vc_found)
98                         break; /* we found a vcnumber that will work - use it */
99         }
100
101         if (i == 0)
102                 vcnum = 0; /* for most common case, ie if one smb session, use
103                               vc zero.  Also for case when no free vcnum, zero
104                               is safest to send (some clients only send zero) */
105         else if (free_vc_found == 0)
106                 vcnum = 1;  /* we can not reuse vc=0 safely, since some servers
107                                 reset all uids on that, but 1 is ok. */
108         else
109                 vcnum = i;
110         ses->vcnum = vcnum;
111 get_vc_num_exit:
112         write_unlock(&cifs_tcp_ses_lock);
113
114         return le16_to_cpu(vcnum);
115 }
116
117 static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB)
118 {
119         __u32 capabilities = 0;
120
121         /* init fields common to all four types of SessSetup */
122         /* Note that offsets for first seven fields in req struct are same  */
123         /*      in CIFS Specs so does not matter which of 3 forms of struct */
124         /*      that we use in next few lines                               */
125         /* Note that header is initialized to zero in header_assemble */
126         pSMB->req.AndXCommand = 0xFF;
127         pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
128         pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
129         pSMB->req.VcNumber = get_next_vcnum(ses);
130
131         /* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */
132
133         /* BB verify whether signing required on neg or just on auth frame
134            (and NTLM case) */
135
136         capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
137                         CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
138
139         if (ses->server->secMode &
140             (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
141                 pSMB->req.hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
142
143         if (ses->capabilities & CAP_UNICODE) {
144                 pSMB->req.hdr.Flags2 |= SMBFLG2_UNICODE;
145                 capabilities |= CAP_UNICODE;
146         }
147         if (ses->capabilities & CAP_STATUS32) {
148                 pSMB->req.hdr.Flags2 |= SMBFLG2_ERR_STATUS;
149                 capabilities |= CAP_STATUS32;
150         }
151         if (ses->capabilities & CAP_DFS) {
152                 pSMB->req.hdr.Flags2 |= SMBFLG2_DFS;
153                 capabilities |= CAP_DFS;
154         }
155         if (ses->capabilities & CAP_UNIX)
156                 capabilities |= CAP_UNIX;
157
158         return capabilities;
159 }
160
161 static void
162 unicode_oslm_strings(char **pbcc_area, const struct nls_table *nls_cp)
163 {
164         char *bcc_ptr = *pbcc_area;
165         int bytes_ret = 0;
166
167         /* Copy OS version */
168         bytes_ret = cifs_strtoUCS((__le16 *)bcc_ptr, "Linux version ", 32,
169                                   nls_cp);
170         bcc_ptr += 2 * bytes_ret;
171         bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, init_utsname()->release,
172                                   32, nls_cp);
173         bcc_ptr += 2 * bytes_ret;
174         bcc_ptr += 2; /* trailing null */
175
176         bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
177                                   32, nls_cp);
178         bcc_ptr += 2 * bytes_ret;
179         bcc_ptr += 2; /* trailing null */
180
181         *pbcc_area = bcc_ptr;
182 }
183
184 static void unicode_domain_string(char **pbcc_area, struct cifsSesInfo *ses,
185                                    const struct nls_table *nls_cp)
186 {
187         char *bcc_ptr = *pbcc_area;
188         int bytes_ret = 0;
189
190         /* copy domain */
191         if (ses->domainName == NULL) {
192                 /* Sending null domain better than using a bogus domain name (as
193                 we did briefly in 2.6.18) since server will use its default */
194                 *bcc_ptr = 0;
195                 *(bcc_ptr+1) = 0;
196                 bytes_ret = 0;
197         } else
198                 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->domainName,
199                                           256, nls_cp);
200         bcc_ptr += 2 * bytes_ret;
201         bcc_ptr += 2;  /* account for null terminator */
202
203         *pbcc_area = bcc_ptr;
204 }
205
206
207 static void unicode_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses,
208                                    const struct nls_table *nls_cp)
209 {
210         char *bcc_ptr = *pbcc_area;
211         int bytes_ret = 0;
212
213         /* BB FIXME add check that strings total less
214         than 335 or will need to send them as arrays */
215
216         /* unicode strings, must be word aligned before the call */
217 /*      if ((long) bcc_ptr % 2) {
218                 *bcc_ptr = 0;
219                 bcc_ptr++;
220         } */
221         /* copy user */
222         if (ses->userName == NULL) {
223                 /* null user mount */
224                 *bcc_ptr = 0;
225                 *(bcc_ptr+1) = 0;
226         } else { /* 300 should be long enough for any conceivable user name */
227                 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->userName,
228                                           300, nls_cp);
229         }
230         bcc_ptr += 2 * bytes_ret;
231         bcc_ptr += 2; /* account for null termination */
232
233         unicode_domain_string(&bcc_ptr, ses, nls_cp);
234         unicode_oslm_strings(&bcc_ptr, nls_cp);
235
236         *pbcc_area = bcc_ptr;
237 }
238
239 static void ascii_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses,
240                                  const struct nls_table *nls_cp)
241 {
242         char *bcc_ptr = *pbcc_area;
243
244         /* copy user */
245         /* BB what about null user mounts - check that we do this BB */
246         /* copy user */
247         if (ses->userName == NULL) {
248                 /* BB what about null user mounts - check that we do this BB */
249         } else { /* 300 should be long enough for any conceivable user name */
250                 strncpy(bcc_ptr, ses->userName, 300);
251         }
252         /* BB improve check for overflow */
253         bcc_ptr += strnlen(ses->userName, 300);
254         *bcc_ptr = 0;
255         bcc_ptr++; /* account for null termination */
256
257         /* copy domain */
258
259         if (ses->domainName != NULL) {
260                 strncpy(bcc_ptr, ses->domainName, 256);
261                 bcc_ptr += strnlen(ses->domainName, 256);
262         } /* else we will send a null domain name
263              so the server will default to its own domain */
264         *bcc_ptr = 0;
265         bcc_ptr++;
266
267         /* BB check for overflow here */
268
269         strcpy(bcc_ptr, "Linux version ");
270         bcc_ptr += strlen("Linux version ");
271         strcpy(bcc_ptr, init_utsname()->release);
272         bcc_ptr += strlen(init_utsname()->release) + 1;
273
274         strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
275         bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
276
277         *pbcc_area = bcc_ptr;
278 }
279
280 static int decode_unicode_ssetup(char **pbcc_area, int bleft,
281                                  struct cifsSesInfo *ses,
282                                  const struct nls_table *nls_cp)
283 {
284         int rc = 0;
285         int words_left, len;
286         char *data = *pbcc_area;
287
288
289
290         cFYI(1, ("bleft %d", bleft));
291
292
293         /* SMB header is unaligned, so cifs servers word align start of
294            Unicode strings */
295         data++;
296         bleft--; /* Windows servers do not always double null terminate
297                     their final Unicode string - in which case we
298                     now will not attempt to decode the byte of junk
299                     which follows it */
300
301         words_left = bleft / 2;
302
303         /* save off server operating system */
304         len = UniStrnlen((wchar_t *) data, words_left);
305
306 /* We look for obvious messed up bcc or strings in response so we do not go off
307    the end since (at least) WIN2K and Windows XP have a major bug in not null
308    terminating last Unicode string in response  */
309         if (len >= words_left)
310                 return rc;
311
312         kfree(ses->serverOS);
313         /* UTF-8 string will not grow more than four times as big as UCS-16 */
314         ses->serverOS = kzalloc((4 * len) + 2 /* trailing null */, GFP_KERNEL);
315         if (ses->serverOS != NULL)
316                 cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len, nls_cp);
317         data += 2 * (len + 1);
318         words_left -= len + 1;
319
320         /* save off server network operating system */
321         len = UniStrnlen((wchar_t *) data, words_left);
322
323         if (len >= words_left)
324                 return rc;
325
326         kfree(ses->serverNOS);
327         ses->serverNOS = kzalloc((4 * len) + 2 /* trailing null */, GFP_KERNEL);
328         if (ses->serverNOS != NULL) {
329                 cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len,
330                                    nls_cp);
331                 if (strncmp(ses->serverNOS, "NT LAN Manager 4", 16) == 0) {
332                         cFYI(1, ("NT4 server"));
333                         ses->flags |= CIFS_SES_NT4;
334                 }
335         }
336         data += 2 * (len + 1);
337         words_left -= len + 1;
338
339         /* save off server domain */
340         len = UniStrnlen((wchar_t *) data, words_left);
341
342         if (len > words_left)
343                 return rc;
344
345         kfree(ses->serverDomain);
346         ses->serverDomain = kzalloc(2 * (len + 1), GFP_KERNEL); /* BB FIXME wrong length */
347         if (ses->serverDomain != NULL) {
348                 cifs_strfromUCS_le(ses->serverDomain, (__le16 *)data, len,
349                                    nls_cp);
350                 ses->serverDomain[2*len] = 0;
351                 ses->serverDomain[(2*len) + 1] = 0;
352         }
353         data += 2 * (len + 1);
354         words_left -= len + 1;
355
356         cFYI(1, ("words left: %d", words_left));
357
358         return rc;
359 }
360
361 static int decode_ascii_ssetup(char **pbcc_area, int bleft,
362                                struct cifsSesInfo *ses,
363                                const struct nls_table *nls_cp)
364 {
365         int rc = 0;
366         int len;
367         char *bcc_ptr = *pbcc_area;
368
369         cFYI(1, ("decode sessetup ascii. bleft %d", bleft));
370
371         len = strnlen(bcc_ptr, bleft);
372         if (len >= bleft)
373                 return rc;
374
375         kfree(ses->serverOS);
376
377         ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
378         if (ses->serverOS)
379                 strncpy(ses->serverOS, bcc_ptr, len);
380         if (strncmp(ses->serverOS, "OS/2", 4) == 0) {
381                         cFYI(1, ("OS/2 server"));
382                         ses->flags |= CIFS_SES_OS2;
383         }
384
385         bcc_ptr += len + 1;
386         bleft -= len + 1;
387
388         len = strnlen(bcc_ptr, bleft);
389         if (len >= bleft)
390                 return rc;
391
392         kfree(ses->serverNOS);
393
394         ses->serverNOS = kzalloc(len + 1, GFP_KERNEL);
395         if (ses->serverNOS)
396                 strncpy(ses->serverNOS, bcc_ptr, len);
397
398         bcc_ptr += len + 1;
399         bleft -= len + 1;
400
401         len = strnlen(bcc_ptr, bleft);
402         if (len > bleft)
403                 return rc;
404
405         /* No domain field in LANMAN case. Domain is
406            returned by old servers in the SMB negprot response */
407         /* BB For newer servers which do not support Unicode,
408            but thus do return domain here we could add parsing
409            for it later, but it is not very important */
410         cFYI(1, ("ascii: bytes left %d", bleft));
411
412         return rc;
413 }
414
415 int
416 CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
417                 const struct nls_table *nls_cp)
418 {
419         int rc = 0;
420         int wct;
421         struct smb_hdr *smb_buf;
422         char *bcc_ptr;
423         char *str_area;
424         SESSION_SETUP_ANDX *pSMB;
425         __u32 capabilities;
426         int count;
427         int resp_buf_type;
428         struct kvec iov[3];
429         enum securityEnum type;
430         __u16 action;
431         int bytes_remaining;
432         struct key *spnego_key = NULL;
433
434         if (ses == NULL)
435                 return -EINVAL;
436
437         type = ses->server->secType;
438
439         cFYI(1, ("sess setup type %d", type));
440         if (type == LANMAN) {
441 #ifndef CONFIG_CIFS_WEAK_PW_HASH
442                 /* LANMAN and plaintext are less secure and off by default.
443                 So we make this explicitly be turned on in kconfig (in the
444                 build) and turned on at runtime (changed from the default)
445                 in proc/fs/cifs or via mount parm.  Unfortunately this is
446                 needed for old Win (e.g. Win95), some obscure NAS and OS/2 */
447                 return -EOPNOTSUPP;
448 #endif
449                 wct = 10; /* lanman 2 style sessionsetup */
450         } else if ((type == NTLM) || (type == NTLMv2)) {
451                 /* For NTLMv2 failures eventually may need to retry NTLM */
452                 wct = 13; /* old style NTLM sessionsetup */
453         } else /* same size: negotiate or auth, NTLMSSP or extended security */
454                 wct = 12;
455
456         rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses,
457                             (void **)&smb_buf);
458         if (rc)
459                 return rc;
460
461         pSMB = (SESSION_SETUP_ANDX *)smb_buf;
462
463         capabilities = cifs_ssetup_hdr(ses, pSMB);
464
465         /* we will send the SMB in three pieces:
466         a fixed length beginning part, an optional
467         SPNEGO blob (which can be zero length), and a
468         last part which will include the strings
469         and rest of bcc area. This allows us to avoid
470         a large buffer 17K allocation */
471         iov[0].iov_base = (char *)pSMB;
472         iov[0].iov_len = smb_buf->smb_buf_length + 4;
473
474         /* setting this here allows the code at the end of the function
475            to free the request buffer if there's an error */
476         resp_buf_type = CIFS_SMALL_BUFFER;
477
478         /* 2000 big enough to fit max user, domain, NOS name etc. */
479         str_area = kmalloc(2000, GFP_KERNEL);
480         if (str_area == NULL) {
481                 rc = -ENOMEM;
482                 goto ssetup_exit;
483         }
484         bcc_ptr = str_area;
485
486         ses->flags &= ~CIFS_SES_LANMAN;
487
488         iov[1].iov_base = NULL;
489         iov[1].iov_len = 0;
490
491         if (type == LANMAN) {
492 #ifdef CONFIG_CIFS_WEAK_PW_HASH
493                 char lnm_session_key[CIFS_SESS_KEY_SIZE];
494
495                 pSMB->req.hdr.Flags2 &= ~SMBFLG2_UNICODE;
496
497                 /* no capabilities flags in old lanman negotiation */
498
499                 pSMB->old_req.PasswordLength = cpu_to_le16(CIFS_SESS_KEY_SIZE);
500                 /* BB calculate hash with password */
501                 /* and copy into bcc */
502
503                 calc_lanman_hash(ses->password, ses->server->cryptKey,
504                                  ses->server->secMode & SECMODE_PW_ENCRYPT ?
505                                         true : false, lnm_session_key);
506
507                 ses->flags |= CIFS_SES_LANMAN;
508                 memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_SESS_KEY_SIZE);
509                 bcc_ptr += CIFS_SESS_KEY_SIZE;
510
511                 /* can not sign if LANMAN negotiated so no need
512                 to calculate signing key? but what if server
513                 changed to do higher than lanman dialect and
514                 we reconnected would we ever calc signing_key? */
515
516                 cFYI(1, ("Negotiating LANMAN setting up strings"));
517                 /* Unicode not allowed for LANMAN dialects */
518                 ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
519 #endif
520         } else if (type == NTLM) {
521                 char ntlm_session_key[CIFS_SESS_KEY_SIZE];
522
523                 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
524                 pSMB->req_no_secext.CaseInsensitivePasswordLength =
525                         cpu_to_le16(CIFS_SESS_KEY_SIZE);
526                 pSMB->req_no_secext.CaseSensitivePasswordLength =
527                         cpu_to_le16(CIFS_SESS_KEY_SIZE);
528
529                 /* calculate session key */
530                 SMBNTencrypt(ses->password, ses->server->cryptKey,
531                              ntlm_session_key);
532
533                 if (first_time) /* should this be moved into common code
534                                   with similar ntlmv2 path? */
535                         cifs_calculate_mac_key(&ses->server->mac_signing_key,
536                                 ntlm_session_key, ses->password);
537                 /* copy session key */
538
539                 memcpy(bcc_ptr, (char *)ntlm_session_key, CIFS_SESS_KEY_SIZE);
540                 bcc_ptr += CIFS_SESS_KEY_SIZE;
541                 memcpy(bcc_ptr, (char *)ntlm_session_key, CIFS_SESS_KEY_SIZE);
542                 bcc_ptr += CIFS_SESS_KEY_SIZE;
543                 if (ses->capabilities & CAP_UNICODE) {
544                         /* unicode strings must be word aligned */
545                         if (iov[0].iov_len % 2) {
546                                 *bcc_ptr = 0;
547                                 bcc_ptr++;
548                         }
549                         unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
550                 } else
551                         ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
552         } else if (type == NTLMv2) {
553                 char *v2_sess_key =
554                         kmalloc(sizeof(struct ntlmv2_resp), GFP_KERNEL);
555
556                 /* BB FIXME change all users of v2_sess_key to
557                    struct ntlmv2_resp */
558
559                 if (v2_sess_key == NULL) {
560                         rc = -ENOMEM;
561                         goto ssetup_exit;
562                 }
563
564                 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
565
566                 /* LM2 password would be here if we supported it */
567                 pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
568                 /*      cpu_to_le16(LM2_SESS_KEY_SIZE); */
569
570                 pSMB->req_no_secext.CaseSensitivePasswordLength =
571                         cpu_to_le16(sizeof(struct ntlmv2_resp));
572
573                 /* calculate session key */
574                 setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp);
575                 if (first_time) /* should this be moved into common code
576                                    with similar ntlmv2 path? */
577                 /*   cifs_calculate_ntlmv2_mac_key(ses->server->mac_signing_key,
578                                 response BB FIXME, v2_sess_key); */
579
580                 /* copy session key */
581
582         /*      memcpy(bcc_ptr, (char *)ntlm_session_key,LM2_SESS_KEY_SIZE);
583                 bcc_ptr += LM2_SESS_KEY_SIZE; */
584                 memcpy(bcc_ptr, (char *)v2_sess_key,
585                        sizeof(struct ntlmv2_resp));
586                 bcc_ptr += sizeof(struct ntlmv2_resp);
587                 kfree(v2_sess_key);
588                 if (ses->capabilities & CAP_UNICODE) {
589                         if (iov[0].iov_len % 2) {
590                                 *bcc_ptr = 0;
591                                 bcc_ptr++;
592                         }
593                         unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
594                 } else
595                         ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
596         } else if (type == Kerberos || type == MSKerberos) {
597 #ifdef CONFIG_CIFS_UPCALL
598                 struct cifs_spnego_msg *msg;
599                 spnego_key = cifs_get_spnego_key(ses);
600                 if (IS_ERR(spnego_key)) {
601                         rc = PTR_ERR(spnego_key);
602                         spnego_key = NULL;
603                         goto ssetup_exit;
604                 }
605
606                 msg = spnego_key->payload.data;
607                 /* check version field to make sure that cifs.upcall is
608                    sending us a response in an expected form */
609                 if (msg->version != CIFS_SPNEGO_UPCALL_VERSION) {
610                         cERROR(1, ("incorrect version of cifs.upcall (expected"
611                                    " %d but got %d)",
612                                    CIFS_SPNEGO_UPCALL_VERSION, msg->version));
613                         rc = -EKEYREJECTED;
614                         goto ssetup_exit;
615                 }
616                 /* bail out if key is too long */
617                 if (msg->sesskey_len >
618                     sizeof(ses->server->mac_signing_key.data.krb5)) {
619                         cERROR(1, ("Kerberos signing key too long (%u bytes)",
620                                 msg->sesskey_len));
621                         rc = -EOVERFLOW;
622                         goto ssetup_exit;
623                 }
624                 if (first_time) {
625                         ses->server->mac_signing_key.len = msg->sesskey_len;
626                         memcpy(ses->server->mac_signing_key.data.krb5,
627                                 msg->data, msg->sesskey_len);
628                 }
629                 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
630                 capabilities |= CAP_EXTENDED_SECURITY;
631                 pSMB->req.Capabilities = cpu_to_le32(capabilities);
632                 iov[1].iov_base = msg->data + msg->sesskey_len;
633                 iov[1].iov_len = msg->secblob_len;
634                 pSMB->req.SecurityBlobLength = cpu_to_le16(iov[1].iov_len);
635
636                 if (ses->capabilities & CAP_UNICODE) {
637                         /* unicode strings must be word aligned */
638                         if ((iov[0].iov_len + iov[1].iov_len) % 2) {
639                                 *bcc_ptr = 0;
640                                 bcc_ptr++;
641                         }
642                         unicode_oslm_strings(&bcc_ptr, nls_cp);
643                         unicode_domain_string(&bcc_ptr, ses, nls_cp);
644                 } else
645                 /* BB: is this right? */
646                         ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
647 #else /* ! CONFIG_CIFS_UPCALL */
648                 cERROR(1, ("Kerberos negotiated but upcall support disabled!"));
649                 rc = -ENOSYS;
650                 goto ssetup_exit;
651 #endif /* CONFIG_CIFS_UPCALL */
652         } else {
653                 cERROR(1, ("secType %d not supported!", type));
654                 rc = -ENOSYS;
655                 goto ssetup_exit;
656         }
657
658         iov[2].iov_base = str_area;
659         iov[2].iov_len = (long) bcc_ptr - (long) str_area;
660
661         count = iov[1].iov_len + iov[2].iov_len;
662         smb_buf->smb_buf_length += count;
663
664         BCC_LE(smb_buf) = cpu_to_le16(count);
665
666         rc = SendReceive2(xid, ses, iov, 3 /* num_iovecs */, &resp_buf_type,
667                           CIFS_STD_OP /* not long */ | CIFS_LOG_ERROR);
668         /* SMB request buf freed in SendReceive2 */
669
670         cFYI(1, ("ssetup rc from sendrecv2 is %d", rc));
671         if (rc)
672                 goto ssetup_exit;
673
674         pSMB = (SESSION_SETUP_ANDX *)iov[0].iov_base;
675         smb_buf = (struct smb_hdr *)iov[0].iov_base;
676
677         if ((smb_buf->WordCount != 3) && (smb_buf->WordCount != 4)) {
678                 rc = -EIO;
679                 cERROR(1, ("bad word count %d", smb_buf->WordCount));
680                 goto ssetup_exit;
681         }
682         action = le16_to_cpu(pSMB->resp.Action);
683         if (action & GUEST_LOGIN)
684                 cFYI(1, ("Guest login")); /* BB mark SesInfo struct? */
685         ses->Suid = smb_buf->Uid;   /* UID left in wire format (le) */
686         cFYI(1, ("UID = %d ", ses->Suid));
687         /* response can have either 3 or 4 word count - Samba sends 3 */
688         /* and lanman response is 3 */
689         bytes_remaining = BCC(smb_buf);
690         bcc_ptr = pByteArea(smb_buf);
691
692         if (smb_buf->WordCount == 4) {
693                 __u16 blob_len;
694                 blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
695                 bcc_ptr += blob_len;
696                 if (blob_len > bytes_remaining) {
697                         cERROR(1, ("bad security blob length %d", blob_len));
698                         rc = -EINVAL;
699                         goto ssetup_exit;
700                 }
701                 bytes_remaining -= blob_len;
702         }
703
704         /* BB check if Unicode and decode strings */
705         if (smb_buf->Flags2 & SMBFLG2_UNICODE)
706                 rc = decode_unicode_ssetup(&bcc_ptr, bytes_remaining,
707                                                    ses, nls_cp);
708         else
709                 rc = decode_ascii_ssetup(&bcc_ptr, bytes_remaining,
710                                          ses, nls_cp);
711
712 ssetup_exit:
713         if (spnego_key) {
714                 key_revoke(spnego_key);
715                 key_put(spnego_key);
716         }
717         kfree(str_area);
718         if (resp_buf_type == CIFS_SMALL_BUFFER) {
719                 cFYI(1, ("ssetup freeing small buf %p", iov[0].iov_base));
720                 cifs_small_buf_release(iov[0].iov_base);
721         } else if (resp_buf_type == CIFS_LARGE_BUFFER)
722                 cifs_buf_release(iov[0].iov_base);
723
724         return rc;
725 }