Showing error 1655

User: Jiri Slaby
Error type: Invalid Pointer Dereference
Error type description: A pointer which is invalid is being dereferenced
File location: fs/cifs/connect.c
Line in file: 2956
Project: Linux Kernel
Project version: 2.6.28
Tools: Smatch (1.59)
Entered: 2013-09-10 07:54:05 UTC


Source:

   1/*
   2 *   fs/cifs/connect.c
   3 *
   4 *   Copyright (C) International Business Machines  Corp., 2002,2008
   5 *   Author(s): Steve French (sfrench@us.ibm.com)
   6 *
   7 *   This library is free software; you can redistribute it and/or modify
   8 *   it under the terms of the GNU Lesser General Public License as published
   9 *   by the Free Software Foundation; either version 2.1 of the License, or
  10 *   (at your option) any later version.
  11 *
  12 *   This library is distributed in the hope that it will be useful,
  13 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
  15 *   the GNU Lesser General Public License for more details.
  16 *
  17 *   You should have received a copy of the GNU Lesser General Public License
  18 *   along with this library; if not, write to the Free Software
  19 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20 */
  21#include <linux/fs.h>
  22#include <linux/net.h>
  23#include <linux/string.h>
  24#include <linux/list.h>
  25#include <linux/wait.h>
  26#include <linux/ipv6.h>
  27#include <linux/pagemap.h>
  28#include <linux/ctype.h>
  29#include <linux/utsname.h>
  30#include <linux/mempool.h>
  31#include <linux/delay.h>
  32#include <linux/completion.h>
  33#include <linux/kthread.h>
  34#include <linux/pagevec.h>
  35#include <linux/freezer.h>
  36#include <asm/uaccess.h>
  37#include <asm/processor.h>
  38#include "cifspdu.h"
  39#include "cifsglob.h"
  40#include "cifsproto.h"
  41#include "cifs_unicode.h"
  42#include "cifs_debug.h"
  43#include "cifs_fs_sb.h"
  44#include "ntlmssp.h"
  45#include "nterr.h"
  46#include "rfc1002pdu.h"
  47#include "cn_cifs.h"
  48
  49#define CIFS_PORT 445
  50#define RFC1001_PORT 139
  51
  52extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
  53                         unsigned char *p24);
  54
  55extern mempool_t *cifs_req_poolp;
  56
  57struct smb_vol {
  58        char *username;
  59        char *password;
  60        char *domainname;
  61        char *UNC;
  62        char *UNCip;
  63        char *in6_addr;   /* ipv6 address as human readable form of in6_addr */
  64        char *iocharset;  /* local code page for mapping to and from Unicode */
  65        char source_rfc1001_name[16]; /* netbios name of client */
  66        char target_rfc1001_name[16]; /* netbios name of server for Win9x/ME */
  67        uid_t linux_uid;
  68        gid_t linux_gid;
  69        mode_t file_mode;
  70        mode_t dir_mode;
  71        unsigned secFlg;
  72        bool rw:1;
  73        bool retry:1;
  74        bool intr:1;
  75        bool setuids:1;
  76        bool override_uid:1;
  77        bool override_gid:1;
  78        bool dynperm:1;
  79        bool noperm:1;
  80        bool no_psx_acl:1; /* set if posix acl support should be disabled */
  81        bool cifs_acl:1;
  82        bool no_xattr:1;   /* set if xattr (EA) support should be disabled*/
  83        bool server_ino:1; /* use inode numbers from server ie UniqueId */
  84        bool direct_io:1;
  85        bool remap:1;      /* set to remap seven reserved chars in filenames */
  86        bool posix_paths:1; /* unset to not ask for posix pathnames. */
  87        bool no_linux_ext:1;
  88        bool sfu_emul:1;
  89        bool nullauth:1;   /* attempt to authenticate with null user */
  90        bool nocase:1;     /* request case insensitive filenames */
  91        bool nobrl:1;      /* disable sending byte range locks to srv */
  92        bool seal:1;       /* request transport encryption on share */
  93        bool nodfs:1;      /* Do not request DFS, even if available */
  94        bool local_lease:1; /* check leases only on local system, not remote */
  95        bool noblocksnd:1;
  96        bool noautotune:1;
  97        unsigned int rsize;
  98        unsigned int wsize;
  99        unsigned int sockopt;
 100        unsigned short int port;
 101        char *prepath;
 102};
 103
 104static int ipv4_connect(struct sockaddr_in *psin_server,
 105                        struct socket **csocket,
 106                        char *netb_name,
 107                        char *server_netb_name,
 108                        bool noblocksnd,
 109                        bool nosndbuf); /* ipv6 never set sndbuf size */
 110static int ipv6_connect(struct sockaddr_in6 *psin_server,
 111                        struct socket **csocket, bool noblocksnd);
 112
 113
 114        /*
 115         * cifs tcp session reconnection
 116         *
 117         * mark tcp session as reconnecting so temporarily locked
 118         * mark all smb sessions as reconnecting for tcp session
 119         * reconnect tcp session
 120         * wake up waiters on reconnection? - (not needed currently)
 121         */
 122
 123static int
 124cifs_reconnect(struct TCP_Server_Info *server)
 125{
 126        int rc = 0;
 127        struct list_head *tmp, *tmp2;
 128        struct cifsSesInfo *ses;
 129        struct cifsTconInfo *tcon;
 130        struct mid_q_entry *mid_entry;
 131
 132        spin_lock(&GlobalMid_Lock);
 133        if (server->tcpStatus == CifsExiting) {
 134                /* the demux thread will exit normally
 135                next time through the loop */
 136                spin_unlock(&GlobalMid_Lock);
 137                return rc;
 138        } else
 139                server->tcpStatus = CifsNeedReconnect;
 140        spin_unlock(&GlobalMid_Lock);
 141        server->maxBuf = 0;
 142
 143        cFYI(1, ("Reconnecting tcp session"));
 144
 145        /* before reconnecting the tcp session, mark the smb session (uid)
 146                and the tid bad so they are not used until reconnected */
 147        read_lock(&cifs_tcp_ses_lock);
 148        list_for_each(tmp, &server->smb_ses_list) {
 149                ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list);
 150                ses->need_reconnect = true;
 151                ses->ipc_tid = 0;
 152                list_for_each(tmp2, &ses->tcon_list) {
 153                        tcon = list_entry(tmp2, struct cifsTconInfo, tcon_list);
 154                        tcon->need_reconnect = true;
 155                }
 156        }
 157        read_unlock(&cifs_tcp_ses_lock);
 158        /* do not want to be sending data on a socket we are freeing */
 159        down(&server->tcpSem);
 160        if (server->ssocket) {
 161                cFYI(1, ("State: 0x%x Flags: 0x%lx", server->ssocket->state,
 162                        server->ssocket->flags));
 163                kernel_sock_shutdown(server->ssocket, SHUT_WR);
 164                cFYI(1, ("Post shutdown state: 0x%x Flags: 0x%lx",
 165                        server->ssocket->state,
 166                        server->ssocket->flags));
 167                sock_release(server->ssocket);
 168                server->ssocket = NULL;
 169        }
 170
 171        spin_lock(&GlobalMid_Lock);
 172        list_for_each(tmp, &server->pending_mid_q) {
 173                mid_entry = list_entry(tmp, struct
 174                                        mid_q_entry,
 175                                        qhead);
 176                if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
 177                                /* Mark other intransit requests as needing
 178                                   retry so we do not immediately mark the
 179                                   session bad again (ie after we reconnect
 180                                   below) as they timeout too */
 181                        mid_entry->midState = MID_RETRY_NEEDED;
 182                }
 183        }
 184        spin_unlock(&GlobalMid_Lock);
 185        up(&server->tcpSem);
 186
 187        while ((server->tcpStatus != CifsExiting) &&
 188               (server->tcpStatus != CifsGood)) {
 189                try_to_freeze();
 190                if (server->addr.sockAddr6.sin6_family == AF_INET6) {
 191                        rc = ipv6_connect(&server->addr.sockAddr6,
 192                                          &server->ssocket, server->noautotune);
 193                } else {
 194                        rc = ipv4_connect(&server->addr.sockAddr,
 195                                        &server->ssocket,
 196                                        server->workstation_RFC1001_name,
 197                                        server->server_RFC1001_name,
 198                                        server->noblocksnd, server->noautotune);
 199                }
 200                if (rc) {
 201                        cFYI(1, ("reconnect error %d", rc));
 202                        msleep(3000);
 203                } else {
 204                        atomic_inc(&tcpSesReconnectCount);
 205                        spin_lock(&GlobalMid_Lock);
 206                        if (server->tcpStatus != CifsExiting)
 207                                server->tcpStatus = CifsGood;
 208                        server->sequence_number = 0;
 209                        spin_unlock(&GlobalMid_Lock);
 210        /*                atomic_set(&server->inFlight,0);*/
 211                        wake_up(&server->response_q);
 212                }
 213        }
 214        return rc;
 215}
 216
 217/*
 218        return codes:
 219                0         not a transact2, or all data present
 220                >0         transact2 with that much data missing
 221                -EINVAL = invalid transact2
 222
 223 */
 224static int check2ndT2(struct smb_hdr *pSMB, unsigned int maxBufSize)
 225{
 226        struct smb_t2_rsp *pSMBt;
 227        int total_data_size;
 228        int data_in_this_rsp;
 229        int remaining;
 230
 231        if (pSMB->Command != SMB_COM_TRANSACTION2)
 232                return 0;
 233
 234        /* check for plausible wct, bcc and t2 data and parm sizes */
 235        /* check for parm and data offset going beyond end of smb */
 236        if (pSMB->WordCount != 10) { /* coalesce_t2 depends on this */
 237                cFYI(1, ("invalid transact2 word count"));
 238                return -EINVAL;
 239        }
 240
 241        pSMBt = (struct smb_t2_rsp *)pSMB;
 242
 243        total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
 244        data_in_this_rsp = le16_to_cpu(pSMBt->t2_rsp.DataCount);
 245
 246        remaining = total_data_size - data_in_this_rsp;
 247
 248        if (remaining == 0)
 249                return 0;
 250        else if (remaining < 0) {
 251                cFYI(1, ("total data %d smaller than data in frame %d",
 252                        total_data_size, data_in_this_rsp));
 253                return -EINVAL;
 254        } else {
 255                cFYI(1, ("missing %d bytes from transact2, check next response",
 256                        remaining));
 257                if (total_data_size > maxBufSize) {
 258                        cERROR(1, ("TotalDataSize %d is over maximum buffer %d",
 259                                total_data_size, maxBufSize));
 260                        return -EINVAL;
 261                }
 262                return remaining;
 263        }
 264}
 265
 266static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB)
 267{
 268        struct smb_t2_rsp *pSMB2 = (struct smb_t2_rsp *)psecond;
 269        struct smb_t2_rsp *pSMBt  = (struct smb_t2_rsp *)pTargetSMB;
 270        int total_data_size;
 271        int total_in_buf;
 272        int remaining;
 273        int total_in_buf2;
 274        char *data_area_of_target;
 275        char *data_area_of_buf2;
 276        __u16 byte_count;
 277
 278        total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
 279
 280        if (total_data_size != le16_to_cpu(pSMB2->t2_rsp.TotalDataCount)) {
 281                cFYI(1, ("total data size of primary and secondary t2 differ"));
 282        }
 283
 284        total_in_buf = le16_to_cpu(pSMBt->t2_rsp.DataCount);
 285
 286        remaining = total_data_size - total_in_buf;
 287
 288        if (remaining < 0)
 289                return -EINVAL;
 290
 291        if (remaining == 0) /* nothing to do, ignore */
 292                return 0;
 293
 294        total_in_buf2 = le16_to_cpu(pSMB2->t2_rsp.DataCount);
 295        if (remaining < total_in_buf2) {
 296                cFYI(1, ("transact2 2nd response contains too much data"));
 297        }
 298
 299        /* find end of first SMB data area */
 300        data_area_of_target = (char *)&pSMBt->hdr.Protocol +
 301                                le16_to_cpu(pSMBt->t2_rsp.DataOffset);
 302        /* validate target area */
 303
 304        data_area_of_buf2 = (char *) &pSMB2->hdr.Protocol +
 305                                        le16_to_cpu(pSMB2->t2_rsp.DataOffset);
 306
 307        data_area_of_target += total_in_buf;
 308
 309        /* copy second buffer into end of first buffer */
 310        memcpy(data_area_of_target, data_area_of_buf2, total_in_buf2);
 311        total_in_buf += total_in_buf2;
 312        pSMBt->t2_rsp.DataCount = cpu_to_le16(total_in_buf);
 313        byte_count = le16_to_cpu(BCC_LE(pTargetSMB));
 314        byte_count += total_in_buf2;
 315        BCC_LE(pTargetSMB) = cpu_to_le16(byte_count);
 316
 317        byte_count = pTargetSMB->smb_buf_length;
 318        byte_count += total_in_buf2;
 319
 320        /* BB also add check that we are not beyond maximum buffer size */
 321
 322        pTargetSMB->smb_buf_length = byte_count;
 323
 324        if (remaining == total_in_buf2) {
 325                cFYI(1, ("found the last secondary response"));
 326                return 0; /* we are done */
 327        } else /* more responses to go */
 328                return 1;
 329
 330}
 331
 332static int
 333cifs_demultiplex_thread(struct TCP_Server_Info *server)
 334{
 335        int length;
 336        unsigned int pdu_length, total_read;
 337        struct smb_hdr *smb_buffer = NULL;
 338        struct smb_hdr *bigbuf = NULL;
 339        struct smb_hdr *smallbuf = NULL;
 340        struct msghdr smb_msg;
 341        struct kvec iov;
 342        struct socket *csocket = server->ssocket;
 343        struct list_head *tmp;
 344        struct cifsSesInfo *ses;
 345        struct task_struct *task_to_wake = NULL;
 346        struct mid_q_entry *mid_entry;
 347        char temp;
 348        bool isLargeBuf = false;
 349        bool isMultiRsp;
 350        int reconnect;
 351
 352        current->flags |= PF_MEMALLOC;
 353        cFYI(1, ("Demultiplex PID: %d", task_pid_nr(current)));
 354
 355        length = atomic_inc_return(&tcpSesAllocCount);
 356        if (length > 1)
 357                mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
 358                                GFP_KERNEL);
 359
 360        set_freezable();
 361        while (server->tcpStatus != CifsExiting) {
 362                if (try_to_freeze())
 363                        continue;
 364                if (bigbuf == NULL) {
 365                        bigbuf = cifs_buf_get();
 366                        if (!bigbuf) {
 367                                cERROR(1, ("No memory for large SMB response"));
 368                                msleep(3000);
 369                                /* retry will check if exiting */
 370                                continue;
 371                        }
 372                } else if (isLargeBuf) {
 373                        /* we are reusing a dirty large buf, clear its start */
 374                        memset(bigbuf, 0, sizeof(struct smb_hdr));
 375                }
 376
 377                if (smallbuf == NULL) {
 378                        smallbuf = cifs_small_buf_get();
 379                        if (!smallbuf) {
 380                                cERROR(1, ("No memory for SMB response"));
 381                                msleep(1000);
 382                                /* retry will check if exiting */
 383                                continue;
 384                        }
 385                        /* beginning of smb buffer is cleared in our buf_get */
 386                } else /* if existing small buf clear beginning */
 387                        memset(smallbuf, 0, sizeof(struct smb_hdr));
 388
 389                isLargeBuf = false;
 390                isMultiRsp = false;
 391                smb_buffer = smallbuf;
 392                iov.iov_base = smb_buffer;
 393                iov.iov_len = 4;
 394                smb_msg.msg_control = NULL;
 395                smb_msg.msg_controllen = 0;
 396                pdu_length = 4; /* enough to get RFC1001 header */
 397incomplete_rcv:
 398                length =
 399                    kernel_recvmsg(csocket, &smb_msg,
 400                                &iov, 1, pdu_length, 0 /* BB other flags? */);
 401
 402                if (server->tcpStatus == CifsExiting) {
 403                        break;
 404                } else if (server->tcpStatus == CifsNeedReconnect) {
 405                        cFYI(1, ("Reconnect after server stopped responding"));
 406                        cifs_reconnect(server);
 407                        cFYI(1, ("call to reconnect done"));
 408                        csocket = server->ssocket;
 409                        continue;
 410                } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
 411                        msleep(1); /* minimum sleep to prevent looping
 412                                allowing socket to clear and app threads to set
 413                                tcpStatus CifsNeedReconnect if server hung */
 414                        if (pdu_length < 4) {
 415                                iov.iov_base = (4 - pdu_length) +
 416                                                        (char *)smb_buffer;
 417                                iov.iov_len = pdu_length;
 418                                smb_msg.msg_control = NULL;
 419                                smb_msg.msg_controllen = 0;
 420                                goto incomplete_rcv;
 421                        } else
 422                                continue;
 423                } else if (length <= 0) {
 424                        if (server->tcpStatus == CifsNew) {
 425                                cFYI(1, ("tcp session abend after SMBnegprot"));
 426                                /* some servers kill the TCP session rather than
 427                                   returning an SMB negprot error, in which
 428                                   case reconnecting here is not going to help,
 429                                   and so simply return error to mount */
 430                                break;
 431                        }
 432                        if (!try_to_freeze() && (length == -EINTR)) {
 433                                cFYI(1, ("cifsd thread killed"));
 434                                break;
 435                        }
 436                        cFYI(1, ("Reconnect after unexpected peek error %d",
 437                                length));
 438                        cifs_reconnect(server);
 439                        csocket = server->ssocket;
 440                        wake_up(&server->response_q);
 441                        continue;
 442                } else if (length < pdu_length) {
 443                        cFYI(1, ("requested %d bytes but only got %d bytes",
 444                                  pdu_length, length));
 445                        pdu_length -= length;
 446                        msleep(1);
 447                        goto incomplete_rcv;
 448                }
 449
 450                /* The right amount was read from socket - 4 bytes */
 451                /* so we can now interpret the length field */
 452
 453                /* the first byte big endian of the length field,
 454                is actually not part of the length but the type
 455                with the most common, zero, as regular data */
 456                temp = *((char *) smb_buffer);
 457
 458                /* Note that FC 1001 length is big endian on the wire,
 459                but we convert it here so it is always manipulated
 460                as host byte order */
 461                pdu_length = be32_to_cpu((__force __be32)smb_buffer->smb_buf_length);
 462                smb_buffer->smb_buf_length = pdu_length;
 463
 464                cFYI(1, ("rfc1002 length 0x%x", pdu_length+4));
 465
 466                if (temp == (char) RFC1002_SESSION_KEEP_ALIVE) {
 467                        continue;
 468                } else if (temp == (char)RFC1002_POSITIVE_SESSION_RESPONSE) {
 469                        cFYI(1, ("Good RFC 1002 session rsp"));
 470                        continue;
 471                } else if (temp == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
 472                        /* we get this from Windows 98 instead of
 473                           an error on SMB negprot response */
 474                        cFYI(1, ("Negative RFC1002 Session Response Error 0x%x)",
 475                                pdu_length));
 476                        if (server->tcpStatus == CifsNew) {
 477                                /* if nack on negprot (rather than
 478                                ret of smb negprot error) reconnecting
 479                                not going to help, ret error to mount */
 480                                break;
 481                        } else {
 482                                /* give server a second to
 483                                clean up before reconnect attempt */
 484                                msleep(1000);
 485                                /* always try 445 first on reconnect
 486                                since we get NACK on some if we ever
 487                                connected to port 139 (the NACK is
 488                                since we do not begin with RFC1001
 489                                session initialize frame) */
 490                                server->addr.sockAddr.sin_port =
 491                                        htons(CIFS_PORT);
 492                                cifs_reconnect(server);
 493                                csocket = server->ssocket;
 494                                wake_up(&server->response_q);
 495                                continue;
 496                        }
 497                } else if (temp != (char) 0) {
 498                        cERROR(1, ("Unknown RFC 1002 frame"));
 499                        cifs_dump_mem(" Received Data: ", (char *)smb_buffer,
 500                                      length);
 501                        cifs_reconnect(server);
 502                        csocket = server->ssocket;
 503                        continue;
 504                }
 505
 506                /* else we have an SMB response */
 507                if ((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) ||
 508                            (pdu_length < sizeof(struct smb_hdr) - 1 - 4)) {
 509                        cERROR(1, ("Invalid size SMB length %d pdu_length %d",
 510                                        length, pdu_length+4));
 511                        cifs_reconnect(server);
 512                        csocket = server->ssocket;
 513                        wake_up(&server->response_q);
 514                        continue;
 515                }
 516
 517                /* else length ok */
 518                reconnect = 0;
 519
 520                if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
 521                        isLargeBuf = true;
 522                        memcpy(bigbuf, smallbuf, 4);
 523                        smb_buffer = bigbuf;
 524                }
 525                length = 0;
 526                iov.iov_base = 4 + (char *)smb_buffer;
 527                iov.iov_len = pdu_length;
 528                for (total_read = 0; total_read < pdu_length;
 529                     total_read += length) {
 530                        length = kernel_recvmsg(csocket, &smb_msg, &iov, 1,
 531                                                pdu_length - total_read, 0);
 532                        if ((server->tcpStatus == CifsExiting) ||
 533                            (length == -EINTR)) {
 534                                /* then will exit */
 535                                reconnect = 2;
 536                                break;
 537                        } else if (server->tcpStatus == CifsNeedReconnect) {
 538                                cifs_reconnect(server);
 539                                csocket = server->ssocket;
 540                                /* Reconnect wakes up rspns q */
 541                                /* Now we will reread sock */
 542                                reconnect = 1;
 543                                break;
 544                        } else if ((length == -ERESTARTSYS) ||
 545                                   (length == -EAGAIN)) {
 546                                msleep(1); /* minimum sleep to prevent looping,
 547                                              allowing socket to clear and app
 548                                              threads to set tcpStatus
 549                                              CifsNeedReconnect if server hung*/
 550                                length = 0;
 551                                continue;
 552                        } else if (length <= 0) {
 553                                cERROR(1, ("Received no data, expecting %d",
 554                                              pdu_length - total_read));
 555                                cifs_reconnect(server);
 556                                csocket = server->ssocket;
 557                                reconnect = 1;
 558                                break;
 559                        }
 560                }
 561                if (reconnect == 2)
 562                        break;
 563                else if (reconnect == 1)
 564                        continue;
 565
 566                length += 4; /* account for rfc1002 hdr */
 567
 568
 569                dump_smb(smb_buffer, length);
 570                if (checkSMB(smb_buffer, smb_buffer->Mid, total_read+4)) {
 571                        cifs_dump_mem("Bad SMB: ", smb_buffer, 48);
 572                        continue;
 573                }
 574
 575
 576                task_to_wake = NULL;
 577                spin_lock(&GlobalMid_Lock);
 578                list_for_each(tmp, &server->pending_mid_q) {
 579                        mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
 580
 581                        if ((mid_entry->mid == smb_buffer->Mid) &&
 582                            (mid_entry->midState == MID_REQUEST_SUBMITTED) &&
 583                            (mid_entry->command == smb_buffer->Command)) {
 584                                if (check2ndT2(smb_buffer,server->maxBuf) > 0) {
 585                                        /* We have a multipart transact2 resp */
 586                                        isMultiRsp = true;
 587                                        if (mid_entry->resp_buf) {
 588                                                /* merge response - fix up 1st*/
 589                                                if (coalesce_t2(smb_buffer,
 590                                                        mid_entry->resp_buf)) {
 591                                                        mid_entry->multiRsp =
 592                                                                 true;
 593                                                        break;
 594                                                } else {
 595                                                        /* all parts received */
 596                                                        mid_entry->multiEnd =
 597                                                                 true;
 598                                                        goto multi_t2_fnd;
 599                                                }
 600                                        } else {
 601                                                if (!isLargeBuf) {
 602                                                        cERROR(1,("1st trans2 resp needs bigbuf"));
 603                                        /* BB maybe we can fix this up,  switch
 604                                           to already allocated large buffer? */
 605                                                } else {
 606                                                        /* Have first buffer */
 607                                                        mid_entry->resp_buf =
 608                                                                 smb_buffer;
 609                                                        mid_entry->largeBuf =
 610                                                                 true;
 611                                                        bigbuf = NULL;
 612                                                }
 613                                        }
 614                                        break;
 615                                }
 616                                mid_entry->resp_buf = smb_buffer;
 617                                mid_entry->largeBuf = isLargeBuf;
 618multi_t2_fnd:
 619                                task_to_wake = mid_entry->tsk;
 620                                mid_entry->midState = MID_RESPONSE_RECEIVED;
 621#ifdef CONFIG_CIFS_STATS2
 622                                mid_entry->when_received = jiffies;
 623#endif
 624                                /* so we do not time out requests to  server
 625                                which is still responding (since server could
 626                                be busy but not dead) */
 627                                server->lstrp = jiffies;
 628                                break;
 629                        }
 630                }
 631                spin_unlock(&GlobalMid_Lock);
 632                if (task_to_wake) {
 633                        /* Was previous buf put in mpx struct for multi-rsp? */
 634                        if (!isMultiRsp) {
 635                                /* smb buffer will be freed by user thread */
 636                                if (isLargeBuf)
 637                                        bigbuf = NULL;
 638                                else
 639                                        smallbuf = NULL;
 640                        }
 641                        wake_up_process(task_to_wake);
 642                } else if (!is_valid_oplock_break(smb_buffer, server) &&
 643                           !isMultiRsp) {
 644                        cERROR(1, ("No task to wake, unknown frame received! "
 645                                   "NumMids %d", midCount.counter));
 646                        cifs_dump_mem("Received Data is: ", (char *)smb_buffer,
 647                                      sizeof(struct smb_hdr));
 648#ifdef CONFIG_CIFS_DEBUG2
 649                        cifs_dump_detail(smb_buffer);
 650                        cifs_dump_mids(server);
 651#endif /* CIFS_DEBUG2 */
 652
 653                }
 654        } /* end while !EXITING */
 655
 656        /* take it off the list, if it's not already */
 657        write_lock(&cifs_tcp_ses_lock);
 658        list_del_init(&server->tcp_ses_list);
 659        write_unlock(&cifs_tcp_ses_lock);
 660
 661        spin_lock(&GlobalMid_Lock);
 662        server->tcpStatus = CifsExiting;
 663        spin_unlock(&GlobalMid_Lock);
 664        wake_up_all(&server->response_q);
 665
 666        /* check if we have blocked requests that need to free */
 667        /* Note that cifs_max_pending is normally 50, but
 668        can be set at module install time to as little as two */
 669        spin_lock(&GlobalMid_Lock);
 670        if (atomic_read(&server->inFlight) >= cifs_max_pending)
 671                atomic_set(&server->inFlight, cifs_max_pending - 1);
 672        /* We do not want to set the max_pending too low or we
 673        could end up with the counter going negative */
 674        spin_unlock(&GlobalMid_Lock);
 675        /* Although there should not be any requests blocked on
 676        this queue it can not hurt to be paranoid and try to wake up requests
 677        that may haven been blocked when more than 50 at time were on the wire
 678        to the same server - they now will see the session is in exit state
 679        and get out of SendReceive.  */
 680        wake_up_all(&server->request_q);
 681        /* give those requests time to exit */
 682        msleep(125);
 683
 684        if (server->ssocket) {
 685                sock_release(csocket);
 686                server->ssocket = NULL;
 687        }
 688        /* buffer usuallly freed in free_mid - need to free it here on exit */
 689        cifs_buf_release(bigbuf);
 690        if (smallbuf) /* no sense logging a debug message if NULL */
 691                cifs_small_buf_release(smallbuf);
 692
 693        /*
 694         * BB: we shouldn't have to do any of this. It shouldn't be
 695         * possible to exit from the thread with active SMB sessions
 696         */
 697        read_lock(&cifs_tcp_ses_lock);
 698        if (list_empty(&server->pending_mid_q)) {
 699                /* loop through server session structures attached to this and
 700                    mark them dead */
 701                list_for_each(tmp, &server->smb_ses_list) {
 702                        ses = list_entry(tmp, struct cifsSesInfo,
 703                                         smb_ses_list);
 704                        ses->status = CifsExiting;
 705                        ses->server = NULL;
 706                }
 707                read_unlock(&cifs_tcp_ses_lock);
 708        } else {
 709                /* although we can not zero the server struct pointer yet,
 710                since there are active requests which may depnd on them,
 711                mark the corresponding SMB sessions as exiting too */
 712                list_for_each(tmp, &server->smb_ses_list) {
 713                        ses = list_entry(tmp, struct cifsSesInfo,
 714                                         smb_ses_list);
 715                        ses->status = CifsExiting;
 716                }
 717
 718                spin_lock(&GlobalMid_Lock);
 719                list_for_each(tmp, &server->pending_mid_q) {
 720                mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
 721                        if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
 722                                cFYI(1, ("Clearing Mid 0x%x - waking up ",
 723                                         mid_entry->mid));
 724                                task_to_wake = mid_entry->tsk;
 725                                if (task_to_wake)
 726                                        wake_up_process(task_to_wake);
 727                        }
 728                }
 729                spin_unlock(&GlobalMid_Lock);
 730                read_unlock(&cifs_tcp_ses_lock);
 731                /* 1/8th of sec is more than enough time for them to exit */
 732                msleep(125);
 733        }
 734
 735        if (!list_empty(&server->pending_mid_q)) {
 736                /* mpx threads have not exited yet give them
 737                at least the smb send timeout time for long ops */
 738                /* due to delays on oplock break requests, we need
 739                to wait at least 45 seconds before giving up
 740                on a request getting a response and going ahead
 741                and killing cifsd */
 742                cFYI(1, ("Wait for exit from demultiplex thread"));
 743                msleep(46000);
 744                /* if threads still have not exited they are probably never
 745                coming home not much else we can do but free the memory */
 746        }
 747
 748        /* last chance to mark ses pointers invalid
 749        if there are any pointing to this (e.g
 750        if a crazy root user tried to kill cifsd
 751        kernel thread explicitly this might happen) */
 752        /* BB: This shouldn't be necessary, see above */
 753        read_lock(&cifs_tcp_ses_lock);
 754        list_for_each(tmp, &server->smb_ses_list) {
 755                ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list);
 756                ses->server = NULL;
 757        }
 758        read_unlock(&cifs_tcp_ses_lock);
 759
 760        kfree(server->hostname);
 761        task_to_wake = xchg(&server->tsk, NULL);
 762        kfree(server);
 763
 764        length = atomic_dec_return(&tcpSesAllocCount);
 765        if (length  > 0)
 766                mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
 767                                GFP_KERNEL);
 768
 769        /* if server->tsk was NULL then wait for a signal before exiting */
 770        if (!task_to_wake) {
 771                set_current_state(TASK_INTERRUPTIBLE);
 772                while (!signal_pending(current)) {
 773                        schedule();
 774                        set_current_state(TASK_INTERRUPTIBLE);
 775                }
 776                set_current_state(TASK_RUNNING);
 777        }
 778
 779        return 0;
 780}
 781
 782/* extract the host portion of the UNC string */
 783static char *
 784extract_hostname(const char *unc)
 785{
 786        const char *src;
 787        char *dst, *delim;
 788        unsigned int len;
 789
 790        /* skip double chars at beginning of string */
 791        /* BB: check validity of these bytes? */
 792        src = unc + 2;
 793
 794        /* delimiter between hostname and sharename is always '\\' now */
 795        delim = strchr(src, '\\');
 796        if (!delim)
 797                return ERR_PTR(-EINVAL);
 798
 799        len = delim - src;
 800        dst = kmalloc((len + 1), GFP_KERNEL);
 801        if (dst == NULL)
 802                return ERR_PTR(-ENOMEM);
 803
 804        memcpy(dst, src, len);
 805        dst[len] = '\0';
 806
 807        return dst;
 808}
 809
 810static int
 811cifs_parse_mount_options(char *options, const char *devname,
 812                         struct smb_vol *vol)
 813{
 814        char *value;
 815        char *data;
 816        unsigned int  temp_len, i, j;
 817        char separator[2];
 818
 819        separator[0] = ',';
 820        separator[1] = 0;
 821
 822        if (Local_System_Name[0] != 0)
 823                memcpy(vol->source_rfc1001_name, Local_System_Name, 15);
 824        else {
 825                char *nodename = utsname()->nodename;
 826                int n = strnlen(nodename, 15);
 827                memset(vol->source_rfc1001_name, 0x20, 15);
 828                for (i = 0; i < n; i++) {
 829                        /* does not have to be perfect mapping since field is
 830                        informational, only used for servers that do not support
 831                        port 445 and it can be overridden at mount time */
 832                        vol->source_rfc1001_name[i] = toupper(nodename[i]);
 833                }
 834        }
 835        vol->source_rfc1001_name[15] = 0;
 836        /* null target name indicates to use *SMBSERVR default called name
 837           if we end up sending RFC1001 session initialize */
 838        vol->target_rfc1001_name[0] = 0;
 839        vol->linux_uid = current->uid;        /* current->euid instead? */
 840        vol->linux_gid = current->gid;
 841        vol->dir_mode = S_IRWXUGO;
 842        /* 2767 perms indicate mandatory locking support */
 843        vol->file_mode = (S_IRWXUGO | S_ISGID) & (~S_IXGRP);
 844
 845        /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
 846        vol->rw = true;
 847        /* default is always to request posix paths. */
 848        vol->posix_paths = 1;
 849
 850        if (!options)
 851                return 1;
 852
 853        if (strncmp(options, "sep=", 4) == 0) {
 854                if (options[4] != 0) {
 855                        separator[0] = options[4];
 856                        options += 5;
 857                } else {
 858                        cFYI(1, ("Null separator not allowed"));
 859                }
 860        }
 861
 862        while ((data = strsep(&options, separator)) != NULL) {
 863                if (!*data)
 864                        continue;
 865                if ((value = strchr(data, '=')) != NULL)
 866                        *value++ = '\0';
 867
 868                /* Have to parse this before we parse for "user" */
 869                if (strnicmp(data, "user_xattr", 10) == 0) {
 870                        vol->no_xattr = 0;
 871                } else if (strnicmp(data, "nouser_xattr", 12) == 0) {
 872                        vol->no_xattr = 1;
 873                } else if (strnicmp(data, "user", 4) == 0) {
 874                        if (!value) {
 875                                printk(KERN_WARNING
 876                                       "CIFS: invalid or missing username\n");
 877                                return 1;        /* needs_arg; */
 878                        } else if (!*value) {
 879                                /* null user, ie anonymous, authentication */
 880                                vol->nullauth = 1;
 881                        }
 882                        if (strnlen(value, 200) < 200) {
 883                                vol->username = value;
 884                        } else {
 885                                printk(KERN_WARNING "CIFS: username too long\n");
 886                                return 1;
 887                        }
 888                } else if (strnicmp(data, "pass", 4) == 0) {
 889                        if (!value) {
 890                                vol->password = NULL;
 891                                continue;
 892                        } else if (value[0] == 0) {
 893                                /* check if string begins with double comma
 894                                   since that would mean the password really
 895                                   does start with a comma, and would not
 896                                   indicate an empty string */
 897                                if (value[1] != separator[0]) {
 898                                        vol->password = NULL;
 899                                        continue;
 900                                }
 901                        }
 902                        temp_len = strlen(value);
 903                        /* removed password length check, NTLM passwords
 904                                can be arbitrarily long */
 905
 906                        /* if comma in password, the string will be
 907                        prematurely null terminated.  Commas in password are
 908                        specified across the cifs mount interface by a double
 909                        comma ie ,, and a comma used as in other cases ie ','
 910                        as a parameter delimiter/separator is single and due
 911                        to the strsep above is temporarily zeroed. */
 912
 913                        /* NB: password legally can have multiple commas and
 914                        the only illegal character in a password is null */
 915
 916                        if ((value[temp_len] == 0) &&
 917                            (value[temp_len+1] == separator[0])) {
 918                                /* reinsert comma */
 919                                value[temp_len] = separator[0];
 920                                temp_len += 2;  /* move after second comma */
 921                                while (value[temp_len] != 0)  {
 922                                        if (value[temp_len] == separator[0]) {
 923                                                if (value[temp_len+1] ==
 924                                                     separator[0]) {
 925                                                /* skip second comma */
 926                                                        temp_len++;
 927                                                } else {
 928                                                /* single comma indicating start
 929                                                         of next parm */
 930                                                        break;
 931                                                }
 932                                        }
 933                                        temp_len++;
 934                                }
 935                                if (value[temp_len] == 0) {
 936                                        options = NULL;
 937                                } else {
 938                                        value[temp_len] = 0;
 939                                        /* point option to start of next parm */
 940                                        options = value + temp_len + 1;
 941                                }
 942                                /* go from value to value + temp_len condensing
 943                                double commas to singles. Note that this ends up
 944                                allocating a few bytes too many, which is ok */
 945                                vol->password = kzalloc(temp_len, GFP_KERNEL);
 946                                if (vol->password == NULL) {
 947                                        printk(KERN_WARNING "CIFS: no memory "
 948                                                            "for password\n");
 949                                        return 1;
 950                                }
 951                                for (i = 0, j = 0; i < temp_len; i++, j++) {
 952                                        vol->password[j] = value[i];
 953                                        if (value[i] == separator[0]
 954                                                && value[i+1] == separator[0]) {
 955                                                /* skip second comma */
 956                                                i++;
 957                                        }
 958                                }
 959                                vol->password[j] = 0;
 960                        } else {
 961                                vol->password = kzalloc(temp_len+1, GFP_KERNEL);
 962                                if (vol->password == NULL) {
 963                                        printk(KERN_WARNING "CIFS: no memory "
 964                                                            "for password\n");
 965                                        return 1;
 966                                }
 967                                strcpy(vol->password, value);
 968                        }
 969                } else if (strnicmp(data, "ip", 2) == 0) {
 970                        if (!value || !*value) {
 971                                vol->UNCip = NULL;
 972                        } else if (strnlen(value, 35) < 35) {
 973                                vol->UNCip = value;
 974                        } else {
 975                                printk(KERN_WARNING "CIFS: ip address "
 976                                                    "too long\n");
 977                                return 1;
 978                        }
 979                } else if (strnicmp(data, "sec", 3) == 0) {
 980                        if (!value || !*value) {
 981                                cERROR(1, ("no security value specified"));
 982                                continue;
 983                        } else if (strnicmp(value, "krb5i", 5) == 0) {
 984                                vol->secFlg |= CIFSSEC_MAY_KRB5 |
 985                                        CIFSSEC_MUST_SIGN;
 986                        } else if (strnicmp(value, "krb5p", 5) == 0) {
 987                                /* vol->secFlg |= CIFSSEC_MUST_SEAL |
 988                                        CIFSSEC_MAY_KRB5; */
 989                                cERROR(1, ("Krb5 cifs privacy not supported"));
 990                                return 1;
 991                        } else if (strnicmp(value, "krb5", 4) == 0) {
 992                                vol->secFlg |= CIFSSEC_MAY_KRB5;
 993                        } else if (strnicmp(value, "ntlmv2i", 7) == 0) {
 994                                vol->secFlg |= CIFSSEC_MAY_NTLMV2 |
 995                                        CIFSSEC_MUST_SIGN;
 996                        } else if (strnicmp(value, "ntlmv2", 6) == 0) {
 997                                vol->secFlg |= CIFSSEC_MAY_NTLMV2;
 998                        } else if (strnicmp(value, "ntlmi", 5) == 0) {
 999                                vol->secFlg |= CIFSSEC_MAY_NTLM |
1000                                        CIFSSEC_MUST_SIGN;
1001                        } else if (strnicmp(value, "ntlm", 4) == 0) {
1002                                /* ntlm is default so can be turned off too */
1003                                vol->secFlg |= CIFSSEC_MAY_NTLM;
1004                        } else if (strnicmp(value, "nontlm", 6) == 0) {
1005                                /* BB is there a better way to do this? */
1006                                vol->secFlg |= CIFSSEC_MAY_NTLMV2;
1007#ifdef CONFIG_CIFS_WEAK_PW_HASH
1008                        } else if (strnicmp(value, "lanman", 6) == 0) {
1009                                vol->secFlg |= CIFSSEC_MAY_LANMAN;
1010#endif
1011                        } else if (strnicmp(value, "none", 4) == 0) {
1012                                vol->nullauth = 1;
1013                        } else {
1014                                cERROR(1, ("bad security option: %s", value));
1015                                return 1;
1016                        }
1017                } else if ((strnicmp(data, "unc", 3) == 0)
1018                           || (strnicmp(data, "target", 6) == 0)
1019                           || (strnicmp(data, "path", 4) == 0)) {
1020                        if (!value || !*value) {
1021                                printk(KERN_WARNING "CIFS: invalid path to "
1022                                                    "network resource\n");
1023                                return 1;        /* needs_arg; */
1024                        }
1025                        if ((temp_len = strnlen(value, 300)) < 300) {
1026                                vol->UNC = kmalloc(temp_len+1, GFP_KERNEL);
1027                                if (vol->UNC == NULL)
1028                                        return 1;
1029                                strcpy(vol->UNC, value);
1030                                if (strncmp(vol->UNC, "//", 2) == 0) {
1031                                        vol->UNC[0] = '\\';
1032                                        vol->UNC[1] = '\\';
1033                                } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
1034                                        printk(KERN_WARNING
1035                                               "CIFS: UNC Path does not begin "
1036                                               "with // or \\\\ \n");
1037                                        return 1;
1038                                }
1039                        } else {
1040                                printk(KERN_WARNING "CIFS: UNC name too long\n");
1041                                return 1;
1042                        }
1043                } else if ((strnicmp(data, "domain", 3) == 0)
1044                           || (strnicmp(data, "workgroup", 5) == 0)) {
1045                        if (!value || !*value) {
1046                                printk(KERN_WARNING "CIFS: invalid domain name\n");
1047                                return 1;        /* needs_arg; */
1048                        }
1049                        /* BB are there cases in which a comma can be valid in
1050                        a domain name and need special handling? */
1051                        if (strnlen(value, 256) < 256) {
1052                                vol->domainname = value;
1053                                cFYI(1, ("Domain name set"));
1054                        } else {
1055                                printk(KERN_WARNING "CIFS: domain name too "
1056                                                    "long\n");
1057                                return 1;
1058                        }
1059                } else if (strnicmp(data, "prefixpath", 10) == 0) {
1060                        if (!value || !*value) {
1061                                printk(KERN_WARNING
1062                                        "CIFS: invalid path prefix\n");
1063                                return 1;       /* needs_argument */
1064                        }
1065                        if ((temp_len = strnlen(value, 1024)) < 1024) {
1066                                if (value[0] != '/')
1067                                        temp_len++;  /* missing leading slash */
1068                                vol->prepath = kmalloc(temp_len+1, GFP_KERNEL);
1069                                if (vol->prepath == NULL)
1070                                        return 1;
1071                                if (value[0] != '/') {
1072                                        vol->prepath[0] = '/';
1073                                        strcpy(vol->prepath+1, value);
1074                                } else
1075                                        strcpy(vol->prepath, value);
1076                                cFYI(1, ("prefix path %s", vol->prepath));
1077                        } else {
1078                                printk(KERN_WARNING "CIFS: prefix too long\n");
1079                                return 1;
1080                        }
1081                } else if (strnicmp(data, "iocharset", 9) == 0) {
1082                        if (!value || !*value) {
1083                                printk(KERN_WARNING "CIFS: invalid iocharset "
1084                                                    "specified\n");
1085                                return 1;        /* needs_arg; */
1086                        }
1087                        if (strnlen(value, 65) < 65) {
1088                                if (strnicmp(value, "default", 7))
1089                                        vol->iocharset = value;
1090                                /* if iocharset not set then load_nls_default
1091                                   is used by caller */
1092                                cFYI(1, ("iocharset set to %s", value));
1093                        } else {
1094                                printk(KERN_WARNING "CIFS: iocharset name "
1095                                                    "too long.\n");
1096                                return 1;
1097                        }
1098                } else if (strnicmp(data, "uid", 3) == 0) {
1099                        if (value && *value) {
1100                                vol->linux_uid =
1101                                        simple_strtoul(value, &value, 0);
1102                                vol->override_uid = 1;
1103                        }
1104                } else if (strnicmp(data, "gid", 3) == 0) {
1105                        if (value && *value) {
1106                                vol->linux_gid =
1107                                        simple_strtoul(value, &value, 0);
1108                                vol->override_gid = 1;
1109                        }
1110                } else if (strnicmp(data, "file_mode", 4) == 0) {
1111                        if (value && *value) {
1112                                vol->file_mode =
1113                                        simple_strtoul(value, &value, 0);
1114                        }
1115                } else if (strnicmp(data, "dir_mode", 4) == 0) {
1116                        if (value && *value) {
1117                                vol->dir_mode =
1118                                        simple_strtoul(value, &value, 0);
1119                        }
1120                } else if (strnicmp(data, "dirmode", 4) == 0) {
1121                        if (value && *value) {
1122                                vol->dir_mode =
1123                                        simple_strtoul(value, &value, 0);
1124                        }
1125                } else if (strnicmp(data, "port", 4) == 0) {
1126                        if (value && *value) {
1127                                vol->port =
1128                                        simple_strtoul(value, &value, 0);
1129                        }
1130                } else if (strnicmp(data, "rsize", 5) == 0) {
1131                        if (value && *value) {
1132                                vol->rsize =
1133                                        simple_strtoul(value, &value, 0);
1134                        }
1135                } else if (strnicmp(data, "wsize", 5) == 0) {
1136                        if (value && *value) {
1137                                vol->wsize =
1138                                        simple_strtoul(value, &value, 0);
1139                        }
1140                } else if (strnicmp(data, "sockopt", 5) == 0) {
1141                        if (value && *value) {
1142                                vol->sockopt =
1143                                        simple_strtoul(value, &value, 0);
1144                        }
1145                } else if (strnicmp(data, "netbiosname", 4) == 0) {
1146                        if (!value || !*value || (*value == ' ')) {
1147                                cFYI(1, ("invalid (empty) netbiosname"));
1148                        } else {
1149                                memset(vol->source_rfc1001_name, 0x20, 15);
1150                                for (i = 0; i < 15; i++) {
1151                                /* BB are there cases in which a comma can be
1152                                valid in this workstation netbios name (and need
1153                                special handling)? */
1154
1155                                /* We do not uppercase netbiosname for user */
1156                                        if (value[i] == 0)
1157                                                break;
1158                                        else
1159                                                vol->source_rfc1001_name[i] =
1160                                                                value[i];
1161                                }
1162                                /* The string has 16th byte zero still from
1163                                set at top of the function  */
1164                                if ((i == 15) && (value[i] != 0))
1165                                        printk(KERN_WARNING "CIFS: netbiosname"
1166                                                " longer than 15 truncated.\n");
1167                        }
1168                } else if (strnicmp(data, "servern", 7) == 0) {
1169                        /* servernetbiosname specified override *SMBSERVER */
1170                        if (!value || !*value || (*value == ' ')) {
1171                                cFYI(1, ("empty server netbiosname specified"));
1172                        } else {
1173                                /* last byte, type, is 0x20 for servr type */
1174                                memset(vol->target_rfc1001_name, 0x20, 16);
1175
1176                                for (i = 0; i < 15; i++) {
1177                                /* BB are there cases in which a comma can be
1178                                   valid in this workstation netbios name
1179                                   (and need special handling)? */
1180
1181                                /* user or mount helper must uppercase
1182                                   the netbiosname */
1183                                        if (value[i] == 0)
1184                                                break;
1185                                        else
1186                                                vol->target_rfc1001_name[i] =
1187                                                                value[i];
1188                                }
1189                                /* The string has 16th byte zero still from
1190                                   set at top of the function  */
1191                                if ((i == 15) && (value[i] != 0))
1192                                        printk(KERN_WARNING "CIFS: server net"
1193                                        "biosname longer than 15 truncated.\n");
1194                        }
1195                } else if (strnicmp(data, "credentials", 4) == 0) {
1196                        /* ignore */
1197                } else if (strnicmp(data, "version", 3) == 0) {
1198                        /* ignore */
1199                } else if (strnicmp(data, "guest", 5) == 0) {
1200                        /* ignore */
1201                } else if (strnicmp(data, "rw", 2) == 0) {
1202                        vol->rw = true;
1203                } else if (strnicmp(data, "noblocksend", 11) == 0) {
1204                        vol->noblocksnd = 1;
1205                } else if (strnicmp(data, "noautotune", 10) == 0) {
1206                        vol->noautotune = 1;
1207                } else if ((strnicmp(data, "suid", 4) == 0) ||
1208                                   (strnicmp(data, "nosuid", 6) == 0) ||
1209                                   (strnicmp(data, "exec", 4) == 0) ||
1210                                   (strnicmp(data, "noexec", 6) == 0) ||
1211                                   (strnicmp(data, "nodev", 5) == 0) ||
1212                                   (strnicmp(data, "noauto", 6) == 0) ||
1213                                   (strnicmp(data, "dev", 3) == 0)) {
1214                        /*  The mount tool or mount.cifs helper (if present)
1215                            uses these opts to set flags, and the flags are read
1216                            by the kernel vfs layer before we get here (ie
1217                            before read super) so there is no point trying to
1218                            parse these options again and set anything and it
1219                            is ok to just ignore them */
1220                        continue;
1221                } else if (strnicmp(data, "ro", 2) == 0) {
1222                        vol->rw = false;
1223                } else if (strnicmp(data, "hard", 4) == 0) {
1224                        vol->retry = 1;
1225                } else if (strnicmp(data, "soft", 4) == 0) {
1226                        vol->retry = 0;
1227                } else if (strnicmp(data, "perm", 4) == 0) {
1228                        vol->noperm = 0;
1229                } else if (strnicmp(data, "noperm", 6) == 0) {
1230                        vol->noperm = 1;
1231                } else if (strnicmp(data, "mapchars", 8) == 0) {
1232                        vol->remap = 1;
1233                } else if (strnicmp(data, "nomapchars", 10) == 0) {
1234                        vol->remap = 0;
1235                } else if (strnicmp(data, "sfu", 3) == 0) {
1236                        vol->sfu_emul = 1;
1237                } else if (strnicmp(data, "nosfu", 5) == 0) {
1238                        vol->sfu_emul = 0;
1239                } else if (strnicmp(data, "nodfs", 5) == 0) {
1240                        vol->nodfs = 1;
1241                } else if (strnicmp(data, "posixpaths", 10) == 0) {
1242                        vol->posix_paths = 1;
1243                } else if (strnicmp(data, "noposixpaths", 12) == 0) {
1244                        vol->posix_paths = 0;
1245                } else if (strnicmp(data, "nounix", 6) == 0) {
1246                        vol->no_linux_ext = 1;
1247                } else if (strnicmp(data, "nolinux", 7) == 0) {
1248                        vol->no_linux_ext = 1;
1249                } else if ((strnicmp(data, "nocase", 6) == 0) ||
1250                           (strnicmp(data, "ignorecase", 10)  == 0)) {
1251                        vol->nocase = 1;
1252                } else if (strnicmp(data, "brl", 3) == 0) {
1253                        vol->nobrl =  0;
1254                } else if ((strnicmp(data, "nobrl", 5) == 0) ||
1255                           (strnicmp(data, "nolock", 6) == 0)) {
1256                        vol->nobrl =  1;
1257                        /* turn off mandatory locking in mode
1258                        if remote locking is turned off since the
1259                        local vfs will do advisory */
1260                        if (vol->file_mode ==
1261                                (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
1262                                vol->file_mode = S_IALLUGO;
1263                } else if (strnicmp(data, "setuids", 7) == 0) {
1264                        vol->setuids = 1;
1265                } else if (strnicmp(data, "nosetuids", 9) == 0) {
1266                        vol->setuids = 0;
1267                } else if (strnicmp(data, "dynperm", 7) == 0) {
1268                        vol->dynperm = true;
1269                } else if (strnicmp(data, "nodynperm", 9) == 0) {
1270                        vol->dynperm = false;
1271                } else if (strnicmp(data, "nohard", 6) == 0) {
1272                        vol->retry = 0;
1273                } else if (strnicmp(data, "nosoft", 6) == 0) {
1274                        vol->retry = 1;
1275                } else if (strnicmp(data, "nointr", 6) == 0) {
1276                        vol->intr = 0;
1277                } else if (strnicmp(data, "intr", 4) == 0) {
1278                        vol->intr = 1;
1279                } else if (strnicmp(data, "serverino", 7) == 0) {
1280                        vol->server_ino = 1;
1281                } else if (strnicmp(data, "noserverino", 9) == 0) {
1282                        vol->server_ino = 0;
1283                } else if (strnicmp(data, "cifsacl", 7) == 0) {
1284                        vol->cifs_acl = 1;
1285                } else if (strnicmp(data, "nocifsacl", 9) == 0) {
1286                        vol->cifs_acl = 0;
1287                } else if (strnicmp(data, "acl", 3) == 0) {
1288                        vol->no_psx_acl = 0;
1289                } else if (strnicmp(data, "noacl", 5) == 0) {
1290                        vol->no_psx_acl = 1;
1291#ifdef CONFIG_CIFS_EXPERIMENTAL
1292                } else if (strnicmp(data, "locallease", 6) == 0) {
1293                        vol->local_lease = 1;
1294#endif
1295                } else if (strnicmp(data, "sign", 4) == 0) {
1296                        vol->secFlg |= CIFSSEC_MUST_SIGN;
1297                } else if (strnicmp(data, "seal", 4) == 0) {
1298                        /* we do not do the following in secFlags because seal
1299                           is a per tree connection (mount) not a per socket
1300                           or per-smb connection option in the protocol */
1301                        /* vol->secFlg |= CIFSSEC_MUST_SEAL; */
1302                        vol->seal = 1;
1303                } else if (strnicmp(data, "direct", 6) == 0) {
1304                        vol->direct_io = 1;
1305                } else if (strnicmp(data, "forcedirectio", 13) == 0) {
1306                        vol->direct_io = 1;
1307                } else if (strnicmp(data, "in6_addr", 8) == 0) {
1308                        if (!value || !*value) {
1309                                vol->in6_addr = NULL;
1310                        } else if (strnlen(value, 49) == 48) {
1311                                vol->in6_addr = value;
1312                        } else {
1313                                printk(KERN_WARNING "CIFS: ip v6 address not "
1314                                                    "48 characters long\n");
1315                                return 1;
1316                        }
1317                } else if (strnicmp(data, "noac", 4) == 0) {
1318                        printk(KERN_WARNING "CIFS: Mount option noac not "
1319                                "supported. Instead set "
1320                                "/proc/fs/cifs/LookupCacheEnabled to 0\n");
1321                } else
1322                        printk(KERN_WARNING "CIFS: Unknown mount option %s\n",
1323                                                data);
1324        }
1325        if (vol->UNC == NULL) {
1326                if (devname == NULL) {
1327                        printk(KERN_WARNING "CIFS: Missing UNC name for mount "
1328                                                "target\n");
1329                        return 1;
1330                }
1331                if ((temp_len = strnlen(devname, 300)) < 300) {
1332                        vol->UNC = kmalloc(temp_len+1, GFP_KERNEL);
1333                        if (vol->UNC == NULL)
1334                                return 1;
1335                        strcpy(vol->UNC, devname);
1336                        if (strncmp(vol->UNC, "//", 2) == 0) {
1337                                vol->UNC[0] = '\\';
1338                                vol->UNC[1] = '\\';
1339                        } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
1340                                printk(KERN_WARNING "CIFS: UNC Path does not "
1341                                                    "begin with // or \\\\ \n");
1342                                return 1;
1343                        }
1344                        value = strpbrk(vol->UNC+2, "/\\");
1345                        if (value)
1346                                *value = '\\';
1347                } else {
1348                        printk(KERN_WARNING "CIFS: UNC name too long\n");
1349                        return 1;
1350                }
1351        }
1352        if (vol->UNCip == NULL)
1353                vol->UNCip = &vol->UNC[2];
1354
1355        return 0;
1356}
1357
1358static struct TCP_Server_Info *
1359cifs_find_tcp_session(struct sockaddr *addr)
1360{
1361        struct list_head *tmp;
1362        struct TCP_Server_Info *server;
1363        struct sockaddr_in *addr4 = (struct sockaddr_in *) addr;
1364        struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) addr;
1365
1366        write_lock(&cifs_tcp_ses_lock);
1367        list_for_each(tmp, &cifs_tcp_ses_list) {
1368                server = list_entry(tmp, struct TCP_Server_Info,
1369                                    tcp_ses_list);
1370                /*
1371                 * the demux thread can exit on its own while still in CifsNew
1372                 * so don't accept any sockets in that state. Since the
1373                 * tcpStatus never changes back to CifsNew it's safe to check
1374                 * for this without a lock.
1375                 */
1376                if (server->tcpStatus == CifsNew)
1377                        continue;
1378
1379                if (addr->sa_family == AF_INET &&
1380                    (addr4->sin_addr.s_addr !=
1381                     server->addr.sockAddr.sin_addr.s_addr))
1382                        continue;
1383                else if (addr->sa_family == AF_INET6 &&
1384                         memcmp(&server->addr.sockAddr6.sin6_addr,
1385                                &addr6->sin6_addr, sizeof(addr6->sin6_addr)))
1386                        continue;
1387
1388                ++server->srv_count;
1389                write_unlock(&cifs_tcp_ses_lock);
1390                cFYI(1, ("Existing tcp session with server found"));
1391                return server;
1392        }
1393        write_unlock(&cifs_tcp_ses_lock);
1394        return NULL;
1395}
1396
1397static void
1398cifs_put_tcp_session(struct TCP_Server_Info *server)
1399{
1400        struct task_struct *task;
1401
1402        write_lock(&cifs_tcp_ses_lock);
1403        if (--server->srv_count > 0) {
1404                write_unlock(&cifs_tcp_ses_lock);
1405                return;
1406        }
1407
1408        list_del_init(&server->tcp_ses_list);
1409        write_unlock(&cifs_tcp_ses_lock);
1410
1411        spin_lock(&GlobalMid_Lock);
1412        server->tcpStatus = CifsExiting;
1413        spin_unlock(&GlobalMid_Lock);
1414
1415        task = xchg(&server->tsk, NULL);
1416        if (task)
1417                force_sig(SIGKILL, task);
1418}
1419
1420static struct cifsSesInfo *
1421cifs_find_smb_ses(struct TCP_Server_Info *server, char *username)
1422{
1423        struct list_head *tmp;
1424        struct cifsSesInfo *ses;
1425
1426        write_lock(&cifs_tcp_ses_lock);
1427        list_for_each(tmp, &server->smb_ses_list) {
1428                ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list);
1429                if (strncmp(ses->userName, username, MAX_USERNAME_SIZE))
1430                        continue;
1431
1432                ++ses->ses_count;
1433                write_unlock(&cifs_tcp_ses_lock);
1434                return ses;
1435        }
1436        write_unlock(&cifs_tcp_ses_lock);
1437        return NULL;
1438}
1439
1440static void
1441cifs_put_smb_ses(struct cifsSesInfo *ses)
1442{
1443        int xid;
1444        struct TCP_Server_Info *server = ses->server;
1445
1446        write_lock(&cifs_tcp_ses_lock);
1447        if (--ses->ses_count > 0) {
1448                write_unlock(&cifs_tcp_ses_lock);
1449                return;
1450        }
1451
1452        list_del_init(&ses->smb_ses_list);
1453        write_unlock(&cifs_tcp_ses_lock);
1454
1455        if (ses->status == CifsGood) {
1456                xid = GetXid();
1457                CIFSSMBLogoff(xid, ses);
1458                _FreeXid(xid);
1459        }
1460        sesInfoFree(ses);
1461        cifs_put_tcp_session(server);
1462}
1463
1464static struct cifsTconInfo *
1465cifs_find_tcon(struct cifsSesInfo *ses, const char *unc)
1466{
1467        struct list_head *tmp;
1468        struct cifsTconInfo *tcon;
1469
1470        write_lock(&cifs_tcp_ses_lock);
1471        list_for_each(tmp, &ses->tcon_list) {
1472                tcon = list_entry(tmp, struct cifsTconInfo, tcon_list);
1473                if (tcon->tidStatus == CifsExiting)
1474                        continue;
1475                if (strncmp(tcon->treeName, unc, MAX_TREE_SIZE))
1476                        continue;
1477
1478                ++tcon->tc_count;
1479                write_unlock(&cifs_tcp_ses_lock);
1480                return tcon;
1481        }
1482        write_unlock(&cifs_tcp_ses_lock);
1483        return NULL;
1484}
1485
1486static void
1487cifs_put_tcon(struct cifsTconInfo *tcon)
1488{
1489        int xid;
1490        struct cifsSesInfo *ses = tcon->ses;
1491
1492        write_lock(&cifs_tcp_ses_lock);
1493        if (--tcon->tc_count > 0) {
1494                write_unlock(&cifs_tcp_ses_lock);
1495                return;
1496        }
1497
1498        list_del_init(&tcon->tcon_list);
1499        write_unlock(&cifs_tcp_ses_lock);
1500
1501        xid = GetXid();
1502        CIFSSMBTDis(xid, tcon);
1503        _FreeXid(xid);
1504
1505        DeleteTconOplockQEntries(tcon);
1506        tconInfoFree(tcon);
1507        cifs_put_smb_ses(ses);
1508}
1509
1510int
1511get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path,
1512             const struct nls_table *nls_codepage, unsigned int *pnum_referrals,
1513             struct dfs_info3_param **preferrals, int remap)
1514{
1515        char *temp_unc;
1516        int rc = 0;
1517
1518        *pnum_referrals = 0;
1519        *preferrals = NULL;
1520
1521        if (pSesInfo->ipc_tid == 0) {
1522                temp_unc = kmalloc(2 /* for slashes */ +
1523                        strnlen(pSesInfo->serverName,
1524                                SERVER_NAME_LEN_WITH_NULL * 2)
1525                                 + 1 + 4 /* slash IPC$ */  + 2,
1526                                GFP_KERNEL);
1527                if (temp_unc == NULL)
1528                        return -ENOMEM;
1529                temp_unc[0] = '\\';
1530                temp_unc[1] = '\\';
1531                strcpy(temp_unc + 2, pSesInfo->serverName);
1532                strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
1533                rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
1534                cFYI(1,
1535                     ("CIFS Tcon rc = %d ipc_tid = %d", rc, pSesInfo->ipc_tid));
1536                kfree(temp_unc);
1537        }
1538        if (rc == 0)
1539                rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
1540                                     pnum_referrals, nls_codepage, remap);
1541        /* BB map targetUNCs to dfs_info3 structures, here or
1542                in CIFSGetDFSRefer BB */
1543
1544        return rc;
1545}
1546
1547#ifdef CONFIG_DEBUG_LOCK_ALLOC
1548static struct lock_class_key cifs_key[2];
1549static struct lock_class_key cifs_slock_key[2];
1550
1551static inline void
1552cifs_reclassify_socket4(struct socket *sock)
1553{
1554        struct sock *sk = sock->sk;
1555        BUG_ON(sock_owned_by_user(sk));
1556        sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS",
1557                &cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]);
1558}
1559
1560static inline void
1561cifs_reclassify_socket6(struct socket *sock)
1562{
1563        struct sock *sk = sock->sk;
1564        BUG_ON(sock_owned_by_user(sk));
1565        sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS",
1566                &cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]);
1567}
1568#else
1569static inline void
1570cifs_reclassify_socket4(struct socket *sock)
1571{
1572}
1573
1574static inline void
1575cifs_reclassify_socket6(struct socket *sock)
1576{
1577}
1578#endif
1579
1580/* See RFC1001 section 14 on representation of Netbios names */
1581static void rfc1002mangle(char *target, char *source, unsigned int length)
1582{
1583        unsigned int i, j;
1584
1585        for (i = 0, j = 0; i < (length); i++) {
1586                /* mask a nibble at a time and encode */
1587                target[j] = 'A' + (0x0F & (source[i] >> 4));
1588                target[j+1] = 'A' + (0x0F & source[i]);
1589                j += 2;
1590        }
1591
1592}
1593
1594
1595static int
1596ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1597             char *netbios_name, char *target_name,
1598             bool noblocksnd, bool noautotune)
1599{
1600        int rc = 0;
1601        int connected = 0;
1602        __be16 orig_port = 0;
1603
1604        if (*csocket == NULL) {
1605                rc = sock_create_kern(PF_INET, SOCK_STREAM,
1606                                      IPPROTO_TCP, csocket);
1607                if (rc < 0) {
1608                        cERROR(1, ("Error %d creating socket", rc));
1609                        *csocket = NULL;
1610                        return rc;
1611                } else {
1612                /* BB other socket options to set KEEPALIVE, NODELAY? */
1613                        cFYI(1, ("Socket created"));
1614                        (*csocket)->sk->sk_allocation = GFP_NOFS;
1615                        cifs_reclassify_socket4(*csocket);
1616                }
1617        }
1618
1619        psin_server->sin_family = AF_INET;
1620        if (psin_server->sin_port) { /* user overrode default port */
1621                rc = (*csocket)->ops->connect(*csocket,
1622                                (struct sockaddr *) psin_server,
1623                                sizeof(struct sockaddr_in), 0);
1624                if (rc >= 0)
1625                        connected = 1;
1626        }
1627
1628        if (!connected) {
1629                /* save original port so we can retry user specified port
1630                        later if fall back ports fail this time  */
1631                orig_port = psin_server->sin_port;
1632
1633                /* do not retry on the same port we just failed on */
1634                if (psin_server->sin_port != htons(CIFS_PORT)) {
1635                        psin_server->sin_port = htons(CIFS_PORT);
1636
1637                        rc = (*csocket)->ops->connect(*csocket,
1638                                        (struct sockaddr *) psin_server,
1639                                        sizeof(struct sockaddr_in), 0);
1640                        if (rc >= 0)
1641                                connected = 1;
1642                }
1643        }
1644        if (!connected) {
1645                psin_server->sin_port = htons(RFC1001_PORT);
1646                rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1647                                              psin_server,
1648                                              sizeof(struct sockaddr_in), 0);
1649                if (rc >= 0)
1650                        connected = 1;
1651        }
1652
1653        /* give up here - unless we want to retry on different
1654                protocol families some day */
1655        if (!connected) {
1656                if (orig_port)
1657                        psin_server->sin_port = orig_port;
1658                cFYI(1, ("Error %d connecting to server via ipv4", rc));
1659                sock_release(*csocket);
1660                *csocket = NULL;
1661                return rc;
1662        }
1663        /* Eventually check for other socket options to change from
1664                the default. sock_setsockopt not used because it expects
1665                user space buffer */
1666         cFYI(1, ("sndbuf %d rcvbuf %d rcvtimeo 0x%lx",
1667                 (*csocket)->sk->sk_sndbuf,
1668                 (*csocket)->sk->sk_rcvbuf, (*csocket)->sk->sk_rcvtimeo));
1669        (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1670        if (!noblocksnd)
1671                (*csocket)->sk->sk_sndtimeo = 3 * HZ;
1672
1673        /* make the bufsizes depend on wsize/rsize and max requests */
1674        if (noautotune) {
1675                if ((*csocket)->sk->sk_sndbuf < (200 * 1024))
1676                        (*csocket)->sk->sk_sndbuf = 200 * 1024;
1677                if ((*csocket)->sk->sk_rcvbuf < (140 * 1024))
1678                        (*csocket)->sk->sk_rcvbuf = 140 * 1024;
1679        }
1680
1681        /* send RFC1001 sessinit */
1682        if (psin_server->sin_port == htons(RFC1001_PORT)) {
1683                /* some servers require RFC1001 sessinit before sending
1684                negprot - BB check reconnection in case where second
1685                sessinit is sent but no second negprot */
1686                struct rfc1002_session_packet *ses_init_buf;
1687                struct smb_hdr *smb_buf;
1688                ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
1689                                       GFP_KERNEL);
1690                if (ses_init_buf) {
1691                        ses_init_buf->trailer.session_req.called_len = 32;
1692                        if (target_name && (target_name[0] != 0)) {
1693                                rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1694                                        target_name, 16);
1695                        } else {
1696                                rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1697                                        DEFAULT_CIFS_CALLED_NAME, 16);
1698                        }
1699
1700                        ses_init_buf->trailer.session_req.calling_len = 32;
1701                        /* calling name ends in null (byte 16) from old smb
1702                        convention. */
1703                        if (netbios_name && (netbios_name[0] != 0)) {
1704                                rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1705                                        netbios_name, 16);
1706                        } else {
1707                                rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1708                                        "LINUX_CIFS_CLNT", 16);
1709                        }
1710                        ses_init_buf->trailer.session_req.scope1 = 0;
1711                        ses_init_buf->trailer.session_req.scope2 = 0;
1712                        smb_buf = (struct smb_hdr *)ses_init_buf;
1713                        /* sizeof RFC1002_SESSION_REQUEST with no scope */
1714                        smb_buf->smb_buf_length = 0x81000044;
1715                        rc = smb_send(*csocket, smb_buf, 0x44,
1716                                (struct sockaddr *)psin_server, noblocksnd);
1717                        kfree(ses_init_buf);
1718                        msleep(1); /* RFC1001 layer in at least one server
1719                                      requires very short break before negprot
1720                                      presumably because not expecting negprot
1721                                      to follow so fast.  This is a simple
1722                                      solution that works without
1723                                      complicating the code and causes no
1724                                      significant slowing down on mount
1725                                      for everyone else */
1726                }
1727                /* else the negprot may still work without this
1728                even though malloc failed */
1729
1730        }
1731
1732        return rc;
1733}
1734
1735static int
1736ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket,
1737             bool noblocksnd)
1738{
1739        int rc = 0;
1740        int connected = 0;
1741        __be16 orig_port = 0;
1742
1743        if (*csocket == NULL) {
1744                rc = sock_create_kern(PF_INET6, SOCK_STREAM,
1745                                      IPPROTO_TCP, csocket);
1746                if (rc < 0) {
1747                        cERROR(1, ("Error %d creating ipv6 socket", rc));
1748                        *csocket = NULL;
1749                        return rc;
1750                } else {
1751                /* BB other socket options to set KEEPALIVE, NODELAY? */
1752                         cFYI(1, ("ipv6 Socket created"));
1753                        (*csocket)->sk->sk_allocation = GFP_NOFS;
1754                        cifs_reclassify_socket6(*csocket);
1755                }
1756        }
1757
1758        psin_server->sin6_family = AF_INET6;
1759
1760        if (psin_server->sin6_port) { /* user overrode default port */
1761                rc = (*csocket)->ops->connect(*csocket,
1762                                (struct sockaddr *) psin_server,
1763                                sizeof(struct sockaddr_in6), 0);
1764                if (rc >= 0)
1765                        connected = 1;
1766        }
1767
1768        if (!connected) {
1769                /* save original port so we can retry user specified port
1770                        later if fall back ports fail this time  */
1771
1772                orig_port = psin_server->sin6_port;
1773                /* do not retry on the same port we just failed on */
1774                if (psin_server->sin6_port != htons(CIFS_PORT)) {
1775                        psin_server->sin6_port = htons(CIFS_PORT);
1776
1777                        rc = (*csocket)->ops->connect(*csocket,
1778                                        (struct sockaddr *) psin_server,
1779                                        sizeof(struct sockaddr_in6), 0);
1780                        if (rc >= 0)
1781                                connected = 1;
1782                }
1783        }
1784        if (!connected) {
1785                psin_server->sin6_port = htons(RFC1001_PORT);
1786                rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1787                                 psin_server, sizeof(struct sockaddr_in6), 0);
1788                if (rc >= 0)
1789                        connected = 1;
1790        }
1791
1792        /* give up here - unless we want to retry on different
1793                protocol families some day */
1794        if (!connected) {
1795                if (orig_port)
1796                        psin_server->sin6_port = orig_port;
1797                cFYI(1, ("Error %d connecting to server via ipv6", rc));
1798                sock_release(*csocket);
1799                *csocket = NULL;
1800                return rc;
1801        }
1802        /* Eventually check for other socket options to change from
1803                the default. sock_setsockopt not used because it expects
1804                user space buffer */
1805        (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1806        if (!noblocksnd)
1807                (*csocket)->sk->sk_sndtimeo = 3 * HZ;
1808
1809
1810        return rc;
1811}
1812
1813void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon,
1814                          struct super_block *sb, struct smb_vol *vol_info)
1815{
1816        /* if we are reconnecting then should we check to see if
1817         * any requested capabilities changed locally e.g. via
1818         * remount but we can not do much about it here
1819         * if they have (even if we could detect it by the following)
1820         * Perhaps we could add a backpointer to array of sb from tcon
1821         * or if we change to make all sb to same share the same
1822         * sb as NFS - then we only have one backpointer to sb.
1823         * What if we wanted to mount the server share twice once with
1824         * and once without posixacls or posix paths? */
1825        __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
1826
1827        if (vol_info && vol_info->no_linux_ext) {
1828                tcon->fsUnixInfo.Capability = 0;
1829                tcon->unix_ext = 0; /* Unix Extensions disabled */
1830                cFYI(1, ("Linux protocol extensions disabled"));
1831                return;
1832        } else if (vol_info)
1833                tcon->unix_ext = 1; /* Unix Extensions supported */
1834
1835        if (tcon->unix_ext == 0) {
1836                cFYI(1, ("Unix extensions disabled so not set on reconnect"));
1837                return;
1838        }
1839
1840        if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
1841                __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
1842
1843                /* check for reconnect case in which we do not
1844                   want to change the mount behavior if we can avoid it */
1845                if (vol_info == NULL) {
1846                        /* turn off POSIX ACL and PATHNAMES if not set
1847                           originally at mount time */
1848                        if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
1849                                cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
1850                        if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
1851                                if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
1852                                        cERROR(1, ("POSIXPATH support change"));
1853                                cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
1854                        } else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
1855                                cERROR(1, ("possible reconnect error"));
1856                                cERROR(1,
1857                                        ("server disabled POSIX path support"));
1858                        }
1859                }
1860
1861                cap &= CIFS_UNIX_CAP_MASK;
1862                if (vol_info && vol_info->no_psx_acl)
1863                        cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
1864                else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
1865                        cFYI(1, ("negotiated posix acl support"));
1866                        if (sb)
1867                                sb->s_flags |= MS_POSIXACL;
1868                }
1869
1870                if (vol_info && vol_info->posix_paths == 0)
1871                        cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
1872                else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
1873                        cFYI(1, ("negotiate posix pathnames"));
1874                        if (sb)
1875                                CIFS_SB(sb)->mnt_cifs_flags |=
1876                                        CIFS_MOUNT_POSIX_PATHS;
1877                }
1878
1879                /* We might be setting the path sep back to a different
1880                form if we are reconnecting and the server switched its
1881                posix path capability for this share */
1882                if (sb && (CIFS_SB(sb)->prepathlen > 0))
1883                        CIFS_SB(sb)->prepath[0] = CIFS_DIR_SEP(CIFS_SB(sb));
1884
1885                if (sb && (CIFS_SB(sb)->rsize > 127 * 1024)) {
1886                        if ((cap & CIFS_UNIX_LARGE_READ_CAP) == 0) {
1887                                CIFS_SB(sb)->rsize = 127 * 1024;
1888                                cFYI(DBG2,
1889                                        ("larger reads not supported by srv"));
1890                        }
1891                }
1892
1893
1894                cFYI(1, ("Negotiate caps 0x%x", (int)cap));
1895#ifdef CONFIG_CIFS_DEBUG2
1896                if (cap & CIFS_UNIX_FCNTL_CAP)
1897                        cFYI(1, ("FCNTL cap"));
1898                if (cap & CIFS_UNIX_EXTATTR_CAP)
1899                        cFYI(1, ("EXTATTR cap"));
1900                if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
1901                        cFYI(1, ("POSIX path cap"));
1902                if (cap & CIFS_UNIX_XATTR_CAP)
1903                        cFYI(1, ("XATTR cap"));
1904                if (cap & CIFS_UNIX_POSIX_ACL_CAP)
1905                        cFYI(1, ("POSIX ACL cap"));
1906                if (cap & CIFS_UNIX_LARGE_READ_CAP)
1907                        cFYI(1, ("very large read cap"));
1908                if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
1909                        cFYI(1, ("very large write cap"));
1910#endif /* CIFS_DEBUG2 */
1911                if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
1912                        if (vol_info == NULL) {
1913                                cFYI(1, ("resetting capabilities failed"));
1914                        } else
1915                                cERROR(1, ("Negotiating Unix capabilities "
1916                                           "with the server failed.  Consider "
1917                                           "mounting with the Unix Extensions\n"
1918                                           "disabled, if problems are found, "
1919                                           "by specifying the nounix mount "
1920                                           "option."));
1921
1922                }
1923        }
1924}
1925
1926static void
1927convert_delimiter(char *path, char delim)
1928{
1929        int i;
1930        char old_delim;
1931
1932        if (path == NULL)
1933                return;
1934
1935        if (delim == '/')
1936                old_delim = '\\';
1937        else
1938                old_delim = '/';
1939
1940        for (i = 0; path[i] != '\0'; i++) {
1941                if (path[i] == old_delim)
1942                        path[i] = delim;
1943        }
1944}
1945
1946static void setup_cifs_sb(struct smb_vol *pvolume_info,
1947                          struct cifs_sb_info *cifs_sb)
1948{
1949        if (pvolume_info->rsize > CIFSMaxBufSize) {
1950                cERROR(1, ("rsize %d too large, using MaxBufSize",
1951                        pvolume_info->rsize));
1952                cifs_sb->rsize = CIFSMaxBufSize;
1953        } else if ((pvolume_info->rsize) &&
1954                        (pvolume_info->rsize <= CIFSMaxBufSize))
1955                cifs_sb->rsize = pvolume_info->rsize;
1956        else /* default */
1957                cifs_sb->rsize = CIFSMaxBufSize;
1958
1959        if (pvolume_info->wsize > PAGEVEC_SIZE * PAGE_CACHE_SIZE) {
1960                cERROR(1, ("wsize %d too large, using 4096 instead",
1961                          pvolume_info->wsize));
1962                cifs_sb->wsize = 4096;
1963        } else if (pvolume_info->wsize)
1964                cifs_sb->wsize = pvolume_info->wsize;
1965        else
1966                cifs_sb->wsize = min_t(const int,
1967                                        PAGEVEC_SIZE * PAGE_CACHE_SIZE,
1968                                        127*1024);
1969                /* old default of CIFSMaxBufSize was too small now
1970                   that SMB Write2 can send multiple pages in kvec.
1971                   RFC1001 does not describe what happens when frame
1972                   bigger than 128K is sent so use that as max in
1973                   conjunction with 52K kvec constraint on arch with 4K
1974                   page size  */
1975
1976        if (cifs_sb->rsize < 2048) {
1977                cifs_sb->rsize = 2048;
1978                /* Windows ME may prefer this */
1979                cFYI(1, ("readsize set to minimum: 2048"));
1980        }
1981        /* calculate prepath */
1982        cifs_sb->prepath = pvolume_info->prepath;
1983        if (cifs_sb->prepath) {
1984                cifs_sb->prepathlen = strlen(cifs_sb->prepath);
1985                /* we can not convert the / to \ in the path
1986                separators in the prefixpath yet because we do not
1987                know (until reset_cifs_unix_caps is called later)
1988                whether POSIX PATH CAP is available. We normalize
1989                the / to \ after reset_cifs_unix_caps is called */
1990                pvolume_info->prepath = NULL;
1991        } else
1992                cifs_sb->prepathlen = 0;
1993        cifs_sb->mnt_uid = pvolume_info->linux_uid;
1994        cifs_sb->mnt_gid = pvolume_info->linux_gid;
1995        cifs_sb->mnt_file_mode = pvolume_info->file_mode;
1996        cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
1997        cFYI(1, ("file mode: 0x%x  dir mode: 0x%x",
1998                cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode));
1999
2000        if (pvolume_info->noperm)
2001                cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
2002        if (pvolume_info->setuids)
2003                cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
2004        if (pvolume_info->server_ino)
2005                cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
2006        if (pvolume_info->remap)
2007                cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
2008        if (pvolume_info->no_xattr)
2009                cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
2010        if (pvolume_info->sfu_emul)
2011                cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
2012        if (pvolume_info->nobrl)
2013                cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
2014        if (pvolume_info->cifs_acl)
2015                cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
2016        if (pvolume_info->override_uid)
2017                cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
2018        if (pvolume_info->override_gid)
2019                cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
2020        if (pvolume_info->dynperm)
2021                cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
2022        if (pvolume_info->direct_io) {
2023                cFYI(1, ("mounting share using direct i/o"));
2024                cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
2025        }
2026
2027        if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
2028                cERROR(1, ("mount option dynperm ignored if cifsacl "
2029                           "mount option supported"));
2030}
2031
2032int
2033cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2034           char *mount_data, const char *devname)
2035{
2036        int rc = 0;
2037        int xid;
2038        struct socket *csocket = NULL;
2039        struct sockaddr addr;
2040        struct sockaddr_in *sin_server = (struct sockaddr_in *) &addr;
2041        struct sockaddr_in6 *sin_server6 = (struct sockaddr_in6 *) &addr;
2042        struct smb_vol volume_info;
2043        struct cifsSesInfo *pSesInfo = NULL;
2044        struct cifsTconInfo *tcon = NULL;
2045        struct TCP_Server_Info *srvTcp = NULL;
2046
2047        xid = GetXid();
2048
2049/* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */
2050
2051        memset(&addr, 0, sizeof(struct sockaddr));
2052        memset(&volume_info, 0, sizeof(struct smb_vol));
2053        if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
2054                rc = -EINVAL;
2055                goto out;
2056        }
2057
2058        if (volume_info.nullauth) {
2059                cFYI(1, ("null user"));
2060                volume_info.username = "";
2061        } else if (volume_info.username) {
2062                /* BB fixme parse for domain name here */
2063                cFYI(1, ("Username: %s", volume_info.username));
2064        } else {
2065                cifserror("No username specified");
2066        /* In userspace mount helper we can get user name from alternate
2067           locations such as env variables and files on disk */
2068                rc = -EINVAL;
2069                goto out;
2070        }
2071
2072        if (volume_info.UNCip && volume_info.UNC) {
2073                rc = cifs_inet_pton(AF_INET, volume_info.UNCip,
2074                                    &sin_server->sin_addr.s_addr);
2075
2076                if (rc <= 0) {
2077                        /* not ipv4 address, try ipv6 */
2078                        rc = cifs_inet_pton(AF_INET6, volume_info.UNCip,
2079                                            &sin_server6->sin6_addr.in6_u);
2080                        if (rc > 0)
2081                                addr.sa_family = AF_INET6;
2082                } else {
2083                        addr.sa_family = AF_INET;
2084                }
2085
2086                if (rc <= 0) {
2087                        /* we failed translating address */
2088                        rc = -EINVAL;
2089                        goto out;
2090                }
2091
2092                cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));
2093                /* success */
2094                rc = 0;
2095        } else if (volume_info.UNCip) {
2096                /* BB using ip addr as server name to connect to the
2097                   DFS root below */
2098                cERROR(1, ("Connecting to DFS root not implemented yet"));
2099                rc = -EINVAL;
2100                goto out;
2101        } else /* which servers DFS root would we conect to */ {
2102                cERROR(1,
2103                       ("CIFS mount error: No UNC path (e.g. -o "
2104                        "unc=//192.168.1.100/public) specified"));
2105                rc = -EINVAL;
2106                goto out;
2107        }
2108
2109        /* this is needed for ASCII cp to Unicode converts */
2110        if (volume_info.iocharset == NULL) {
2111                cifs_sb->local_nls = load_nls_default();
2112        /* load_nls_default can not return null */
2113        } else {
2114                cifs_sb->local_nls = load_nls(volume_info.iocharset);
2115                if (cifs_sb->local_nls == NULL) {
2116                        cERROR(1, ("CIFS mount error: iocharset %s not found",
2117                                 volume_info.iocharset));
2118                        rc = -ELIBACC;
2119                        goto out;
2120                }
2121        }
2122
2123        srvTcp = cifs_find_tcp_session(&addr);
2124        if (!srvTcp) { /* create socket */
2125                if (addr.sa_family == AF_INET6) {
2126                        cFYI(1, ("attempting ipv6 connect"));
2127                        /* BB should we allow ipv6 on port 139? */
2128                        /* other OS never observed in Wild doing 139 with v6 */
2129                        sin_server6->sin6_port = htons(volume_info.port);
2130                        rc = ipv6_connect(sin_server6, &csocket,
2131                                        volume_info.noblocksnd);
2132                } else {
2133                        sin_server->sin_port = htons(volume_info.port);
2134                        rc = ipv4_connect(sin_server, &csocket,
2135                                  volume_info.source_rfc1001_name,
2136                                  volume_info.target_rfc1001_name,
2137                                  volume_info.noblocksnd,
2138                                  volume_info.noautotune);
2139                }
2140                if (rc < 0) {
2141                        cERROR(1, ("Error connecting to socket. "
2142                                   "Aborting operation"));
2143                        if (csocket != NULL)
2144                                sock_release(csocket);
2145                        goto out;
2146                }
2147
2148                srvTcp = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
2149                if (!srvTcp) {
2150                        rc = -ENOMEM;
2151                        sock_release(csocket);
2152                        goto out;
2153                } else {
2154                        srvTcp->noblocksnd = volume_info.noblocksnd;
2155                        srvTcp->noautotune = volume_info.noautotune;
2156                        if (addr.sa_family == AF_INET6)
2157                                memcpy(&srvTcp->addr.sockAddr6, sin_server6,
2158                                        sizeof(struct sockaddr_in6));
2159                        else
2160                                memcpy(&srvTcp->addr.sockAddr, sin_server,
2161                                        sizeof(struct sockaddr_in));
2162                        atomic_set(&srvTcp->inFlight, 0);
2163                        /* BB Add code for ipv6 case too */
2164                        srvTcp->ssocket = csocket;
2165                        srvTcp->hostname = extract_hostname(volume_info.UNC);
2166                        if (IS_ERR(srvTcp->hostname)) {
2167                                rc = PTR_ERR(srvTcp->hostname);
2168                                sock_release(csocket);
2169                                goto out;
2170                        }
2171                        init_waitqueue_head(&srvTcp->response_q);
2172                        init_waitqueue_head(&srvTcp->request_q);
2173                        INIT_LIST_HEAD(&srvTcp->pending_mid_q);
2174                        /* at this point we are the only ones with the pointer
2175                        to the struct since the kernel thread not created yet
2176                        so no need to spinlock this init of tcpStatus */
2177                        srvTcp->tcpStatus = CifsNew;
2178                        init_MUTEX(&srvTcp->tcpSem);
2179                        srvTcp->tsk = kthread_run((void *)(void *)cifs_demultiplex_thread, srvTcp, "cifsd");
2180                        if (IS_ERR(srvTcp->tsk)) {
2181                                rc = PTR_ERR(srvTcp->tsk);
2182                                cERROR(1, ("error %d create cifsd thread", rc));
2183                                srvTcp->tsk = NULL;
2184                                sock_release(csocket);
2185                                kfree(srvTcp->hostname);
2186                                goto out;
2187                        }
2188                        rc = 0;
2189                        memcpy(srvTcp->workstation_RFC1001_name,
2190                                volume_info.source_rfc1001_name, 16);
2191                        memcpy(srvTcp->server_RFC1001_name,
2192                                volume_info.target_rfc1001_name, 16);
2193                        srvTcp->sequence_number = 0;
2194                        INIT_LIST_HEAD(&srvTcp->tcp_ses_list);
2195                        INIT_LIST_HEAD(&srvTcp->smb_ses_list);
2196                        ++srvTcp->srv_count;
2197                        write_lock(&cifs_tcp_ses_lock);
2198                        list_add(&srvTcp->tcp_ses_list,
2199                                 &cifs_tcp_ses_list);
2200                        write_unlock(&cifs_tcp_ses_lock);
2201                }
2202        }
2203
2204        pSesInfo = cifs_find_smb_ses(srvTcp, volume_info.username);
2205        if (pSesInfo) {
2206                cFYI(1, ("Existing smb sess found (status=%d)",
2207                        pSesInfo->status));
2208                /*
2209                 * The existing SMB session already has a reference to srvTcp,
2210                 * so we can put back the extra one we got before
2211                 */
2212                cifs_put_tcp_session(srvTcp);
2213
2214                down(&pSesInfo->sesSem);
2215                if (pSesInfo->need_reconnect) {
2216                        cFYI(1, ("Session needs reconnect"));
2217                        rc = cifs_setup_session(xid, pSesInfo,
2218                                                cifs_sb->local_nls);
2219                }
2220                up(&pSesInfo->sesSem);
2221        } else if (!rc) {
2222                cFYI(1, ("Existing smb sess not found"));
2223                pSesInfo = sesInfoAlloc();
2224                if (pSesInfo == NULL) {
2225                        rc = -ENOMEM;
2226                        goto mount_fail_check;
2227                }
2228
2229                /* new SMB session uses our srvTcp ref */
2230                pSesInfo->server = srvTcp;
2231                sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
2232                        NIPQUAD(sin_server->sin_addr.s_addr));
2233
2234                write_lock(&cifs_tcp_ses_lock);
2235                list_add(&pSesInfo->smb_ses_list, &srvTcp->smb_ses_list);
2236                write_unlock(&cifs_tcp_ses_lock);
2237
2238                /* volume_info.password freed at unmount */
2239                if (volume_info.password) {
2240                        pSesInfo->password = volume_info.password;
2241                        /* set to NULL to prevent freeing on exit */
2242                        volume_info.password = NULL;
2243                }
2244                if (volume_info.username)
2245                        strncpy(pSesInfo->userName, volume_info.username,
2246                                MAX_USERNAME_SIZE);
2247                if (volume_info.domainname) {
2248                        int len = strlen(volume_info.domainname);
2249                        pSesInfo->domainName = kmalloc(len + 1, GFP_KERNEL);
2250                        if (pSesInfo->domainName)
2251                                strcpy(pSesInfo->domainName,
2252                                        volume_info.domainname);
2253                }
2254                pSesInfo->linux_uid = volume_info.linux_uid;
2255                pSesInfo->overrideSecFlg = volume_info.secFlg;
2256                down(&pSesInfo->sesSem);
2257
2258                /* BB FIXME need to pass vol->secFlgs BB */
2259                rc = cifs_setup_session(xid, pSesInfo,
2260                                        cifs_sb->local_nls);
2261                up(&pSesInfo->sesSem);
2262        }
2263
2264        /* search for existing tcon to this server share */
2265        if (!rc) {
2266                setup_cifs_sb(&volume_info, cifs_sb);
2267
2268                tcon = cifs_find_tcon(pSesInfo, volume_info.UNC);
2269                if (tcon) {
2270                        cFYI(1, ("Found match on UNC path"));
2271                        /* existing tcon already has a reference */
2272                        cifs_put_smb_ses(pSesInfo);
2273                        if (tcon->seal != volume_info.seal)
2274                                cERROR(1, ("transport encryption setting "
2275                                           "conflicts with existing tid"));
2276                } else {
2277                        tcon = tconInfoAlloc();
2278                        if (tcon == NULL) {
2279                                rc = -ENOMEM;
2280                                goto mount_fail_check;
2281                        }
2282                        tcon->ses = pSesInfo;
2283
2284                        /* check for null share name ie connect to dfs root */
2285                        if ((strchr(volume_info.UNC + 3, '\\') == NULL)
2286                            && (strchr(volume_info.UNC + 3, '/') == NULL)) {
2287                                /* rc = connect_to_dfs_path(...) */
2288                                cFYI(1, ("DFS root not supported"));
2289                                rc = -ENODEV;
2290                                goto mount_fail_check;
2291                        } else {
2292                                /* BB Do we need to wrap sesSem around
2293                                 * this TCon call and Unix SetFS as
2294                                 * we do on SessSetup and reconnect? */
2295                                rc = CIFSTCon(xid, pSesInfo, volume_info.UNC,
2296                                              tcon, cifs_sb->local_nls);
2297                                cFYI(1, ("CIFS Tcon rc = %d", rc));
2298                                if (volume_info.nodfs) {
2299                                        tcon->Flags &= ~SMB_SHARE_IS_IN_DFS;
2300                                        cFYI(1, ("DFS disabled (%d)",
2301                                                tcon->Flags));
2302                                }
2303                        }
2304                        if (rc)
2305                                goto mount_fail_check;
2306                        tcon->seal = volume_info.seal;
2307                        write_lock(&cifs_tcp_ses_lock);
2308                        list_add(&tcon->tcon_list, &pSesInfo->tcon_list);
2309                        write_unlock(&cifs_tcp_ses_lock);
2310                }
2311
2312                /* we can have only one retry value for a connection
2313                   to a share so for resources mounted more than once
2314                   to the same server share the last value passed in
2315                   for the retry flag is used */
2316                tcon->retry = volume_info.retry;
2317                tcon->nocase = volume_info.nocase;
2318                tcon->local_lease = volume_info.local_lease;
2319        }
2320        if (pSesInfo) {
2321                if (pSesInfo->capabilities & CAP_LARGE_FILES) {
2322                        sb->s_maxbytes = (u64) 1 << 63;
2323                } else
2324                        sb->s_maxbytes = (u64) 1 << 31;        /* 2 GB */
2325        }
2326
2327        /* BB FIXME fix time_gran to be larger for LANMAN sessions */
2328        sb->s_time_gran = 100;
2329
2330mount_fail_check:
2331        /* on error free sesinfo and tcon struct if needed */
2332        if (rc) {
2333                /* If find_unc succeeded then rc == 0 so we can not end */
2334                /* up accidently freeing someone elses tcon struct */
2335                if (tcon)
2336                        cifs_put_tcon(tcon);
2337                else if (pSesInfo)
2338                        cifs_put_smb_ses(pSesInfo);
2339                else
2340                        cifs_put_tcp_session(srvTcp);
2341                goto out;
2342        }
2343        cifs_sb->tcon = tcon;
2344
2345        /* do not care if following two calls succeed - informational */
2346        if (!tcon->ipc) {
2347                CIFSSMBQFSDeviceInfo(xid, tcon);
2348                CIFSSMBQFSAttributeInfo(xid, tcon);
2349        }
2350
2351        /* tell server which Unix caps we support */
2352        if (tcon->ses->capabilities & CAP_UNIX)
2353                /* reset of caps checks mount to see if unix extensions
2354                   disabled for just this mount */
2355                reset_cifs_unix_caps(xid, tcon, sb, &volume_info);
2356        else
2357                tcon->unix_ext = 0; /* server does not support them */
2358
2359        /* convert forward to back slashes in prepath here if needed */
2360        if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) == 0)
2361                convert_delimiter(cifs_sb->prepath, CIFS_DIR_SEP(cifs_sb));
2362
2363        if ((tcon->unix_ext == 0) && (cifs_sb->rsize > (1024 * 127))) {
2364                cifs_sb->rsize = 1024 * 127;
2365                cFYI(DBG2, ("no very large read support, rsize now 127K"));
2366        }
2367        if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X))
2368                cifs_sb->wsize = min(cifs_sb->wsize,
2369                               (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE));
2370        if (!(tcon->ses->capabilities & CAP_LARGE_READ_X))
2371                cifs_sb->rsize = min(cifs_sb->rsize,
2372                               (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE));
2373
2374        /* volume_info.password is freed above when existing session found
2375        (in which case it is not needed anymore) but when new sesion is created
2376        the password ptr is put in the new session structure (in which case the
2377        password will be freed at unmount time) */
2378out:
2379        /* zero out password before freeing */
2380        if (volume_info.password != NULL) {
2381                memset(volume_info.password, 0, strlen(volume_info.password));
2382                kfree(volume_info.password);
2383        }
2384        kfree(volume_info.UNC);
2385        kfree(volume_info.prepath);
2386        FreeXid(xid);
2387        return rc;
2388}
2389
2390static int
2391CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2392              char session_key[CIFS_SESS_KEY_SIZE],
2393              const struct nls_table *nls_codepage)
2394{
2395        struct smb_hdr *smb_buffer;
2396        struct smb_hdr *smb_buffer_response;
2397        SESSION_SETUP_ANDX *pSMB;
2398        SESSION_SETUP_ANDX *pSMBr;
2399        char *bcc_ptr;
2400        char *user;
2401        char *domain;
2402        int rc = 0;
2403        int remaining_words = 0;
2404        int bytes_returned = 0;
2405        int len;
2406        __u32 capabilities;
2407        __u16 count;
2408
2409        cFYI(1, ("In sesssetup"));
2410        if (ses == NULL)
2411                return -EINVAL;
2412        user = ses->userName;
2413        domain = ses->domainName;
2414        smb_buffer = cifs_buf_get();
2415
2416        if (smb_buffer == NULL)
2417                return -ENOMEM;
2418
2419        smb_buffer_response = smb_buffer;
2420        pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2421
2422        /* send SMBsessionSetup here */
2423        header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2424                        NULL /* no tCon exists yet */ , 13 /* wct */ );
2425
2426        smb_buffer->Mid = GetNextMid(ses->server);
2427        pSMB->req_no_secext.AndXCommand = 0xFF;
2428        pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2429        pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2430
2431        if (ses->server->secMode &
2432                        (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2433                smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2434
2435        capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2436                CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
2437        if (ses->capabilities & CAP_UNICODE) {
2438                smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2439                capabilities |= CAP_UNICODE;
2440        }
2441        if (ses->capabilities & CAP_STATUS32) {
2442                smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2443                capabilities |= CAP_STATUS32;
2444        }
2445        if (ses->capabilities & CAP_DFS) {
2446                smb_buffer->Flags2 |= SMBFLG2_DFS;
2447                capabilities |= CAP_DFS;
2448        }
2449        pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
2450
2451        pSMB->req_no_secext.CaseInsensitivePasswordLength =
2452                cpu_to_le16(CIFS_SESS_KEY_SIZE);
2453
2454        pSMB->req_no_secext.CaseSensitivePasswordLength =
2455            cpu_to_le16(CIFS_SESS_KEY_SIZE);
2456        bcc_ptr = pByteArea(smb_buffer);
2457        memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE);
2458        bcc_ptr += CIFS_SESS_KEY_SIZE;
2459        memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE);
2460        bcc_ptr += CIFS_SESS_KEY_SIZE;
2461
2462        if (ses->capabilities & CAP_UNICODE) {
2463                if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
2464                        *bcc_ptr = 0;
2465                        bcc_ptr++;
2466                }
2467                if (user == NULL)
2468                        bytes_returned = 0; /* skip null user */
2469                else
2470                        bytes_returned =
2471                                cifs_strtoUCS((__le16 *) bcc_ptr, user, 100,
2472                                        nls_codepage);
2473                /* convert number of 16 bit words to bytes */
2474                bcc_ptr += 2 * bytes_returned;
2475                bcc_ptr += 2;        /* trailing null */
2476                if (domain == NULL)
2477                        bytes_returned =
2478                            cifs_strtoUCS((__le16 *) bcc_ptr,
2479                                          "CIFS_LINUX_DOM", 32, nls_codepage);
2480                else
2481                        bytes_returned =
2482                            cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
2483                                          nls_codepage);
2484                bcc_ptr += 2 * bytes_returned;
2485                bcc_ptr += 2;
2486                bytes_returned =
2487                    cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
2488                                  32, nls_codepage);
2489                bcc_ptr += 2 * bytes_returned;
2490                bytes_returned =
2491                    cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release,
2492                                  32, nls_codepage);
2493                bcc_ptr += 2 * bytes_returned;
2494                bcc_ptr += 2;
2495                bytes_returned =
2496                    cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
2497                                  64, nls_codepage);
2498                bcc_ptr += 2 * bytes_returned;
2499                bcc_ptr += 2;
2500        } else {
2501                if (user != NULL) {
2502                    strncpy(bcc_ptr, user, 200);
2503                    bcc_ptr += strnlen(user, 200);
2504                }
2505                *bcc_ptr = 0;
2506                bcc_ptr++;
2507                if (domain == NULL) {
2508                        strcpy(bcc_ptr, "CIFS_LINUX_DOM");
2509                        bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
2510                } else {
2511                        strncpy(bcc_ptr, domain, 64);
2512                        bcc_ptr += strnlen(domain, 64);
2513                        *bcc_ptr = 0;
2514                        bcc_ptr++;
2515                }
2516                strcpy(bcc_ptr, "Linux version ");
2517                bcc_ptr += strlen("Linux version ");
2518                strcpy(bcc_ptr, utsname()->release);
2519                bcc_ptr += strlen(utsname()->release) + 1;
2520                strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2521                bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2522        }
2523        count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2524        smb_buffer->smb_buf_length += count;
2525        pSMB->req_no_secext.ByteCount = cpu_to_le16(count);
2526
2527        rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2528                         &bytes_returned, CIFS_LONG_OP);
2529        if (rc) {
2530/* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
2531        } else if ((smb_buffer_response->WordCount == 3)
2532                   || (smb_buffer_response->WordCount == 4)) {
2533                __u16 action = le16_to_cpu(pSMBr->resp.Action);
2534                __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2535                if (action & GUEST_LOGIN)
2536                        cFYI(1, (" Guest login")); /* BB mark SesInfo struct? */
2537                ses->Suid = smb_buffer_response->Uid; /* UID left in wire format
2538                                                         (little endian) */
2539                cFYI(1, ("UID = %d ", ses->Suid));
2540        /* response can have either 3 or 4 word count - Samba sends 3 */
2541                bcc_ptr = pByteArea(smb_buffer_response);
2542                if ((pSMBr->resp.hdr.WordCount == 3)
2543                    || ((pSMBr->resp.hdr.WordCount == 4)
2544                        && (blob_len < pSMBr->resp.ByteCount))) {
2545                        if (pSMBr->resp.hdr.WordCount == 4)
2546                                bcc_ptr += blob_len;
2547
2548                        if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2549                                if ((long) (bcc_ptr) % 2) {
2550                                        remaining_words =
2551                                            (BCC(smb_buffer_response) - 1) / 2;
2552                                        /* Unicode strings must be word
2553                                           aligned */
2554                                        bcc_ptr++;
2555                                } else {
2556                                        remaining_words =
2557                                                BCC(smb_buffer_response) / 2;
2558                                }
2559                                len =
2560                                    UniStrnlen((wchar_t *) bcc_ptr,
2561                                               remaining_words - 1);
2562/* We look for obvious messed up bcc or strings in response so we do not go off
2563   the end since (at least) WIN2K and Windows XP have a major bug in not null
2564   terminating last Unicode string in response  */
2565                                if (ses->serverOS)
2566                                        kfree(ses->serverOS);
2567                                ses->serverOS = kzalloc(2 * (len + 1),
2568                                                        GFP_KERNEL);
2569                                if (ses->serverOS == NULL)
2570                                        goto sesssetup_nomem;
2571                                cifs_strfromUCS_le(ses->serverOS,
2572                                                   (__le16 *)bcc_ptr,
2573                                                   len, nls_codepage);
2574                                bcc_ptr += 2 * (len + 1);
2575                                remaining_words -= len + 1;
2576                                ses->serverOS[2 * len] = 0;
2577                                ses->serverOS[1 + (2 * len)] = 0;
2578                                if (remaining_words > 0) {
2579                                        len = UniStrnlen((wchar_t *)bcc_ptr,
2580                                                         remaining_words-1);
2581                                        kfree(ses->serverNOS);
2582                                        ses->serverNOS = kzalloc(2 * (len + 1),
2583                                                                 GFP_KERNEL);
2584                                        if (ses->serverNOS == NULL)
2585                                                goto sesssetup_nomem;
2586                                        cifs_strfromUCS_le(ses->serverNOS,
2587                                                           (__le16 *)bcc_ptr,
2588                                                           len, nls_codepage);
2589                                        bcc_ptr += 2 * (len + 1);
2590                                        ses->serverNOS[2 * len] = 0;
2591                                        ses->serverNOS[1 + (2 * len)] = 0;
2592                                        if (strncmp(ses->serverNOS,
2593                                                "NT LAN Manager 4", 16) == 0) {
2594                                                cFYI(1, ("NT4 server"));
2595                                                ses->flags |= CIFS_SES_NT4;
2596                                        }
2597                                        remaining_words -= len + 1;
2598                                        if (remaining_words > 0) {
2599                                                len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2600                                /* last string is not always null terminated
2601                                   (for e.g. for Windows XP & 2000) */
2602                                                if (ses->serverDomain)
2603                                                        kfree(ses->serverDomain);
2604                                                ses->serverDomain =
2605                                                    kzalloc(2*(len+1),
2606                                                            GFP_KERNEL);
2607                                                if (ses->serverDomain == NULL)
2608                                                        goto sesssetup_nomem;
2609                                                cifs_strfromUCS_le(ses->serverDomain,
2610                                                        (__le16 *)bcc_ptr,
2611                                                        len, nls_codepage);
2612                                                bcc_ptr += 2 * (len + 1);
2613                                                ses->serverDomain[2*len] = 0;
2614                                                ses->serverDomain[1+(2*len)] = 0;
2615                                        } else { /* else no more room so create
2616                                                  dummy domain string */
2617                                                if (ses->serverDomain)
2618                                                        kfree(ses->serverDomain);
2619                                                ses->serverDomain =
2620                                                        kzalloc(2, GFP_KERNEL);
2621                                        }
2622                                } else { /* no room so create dummy domain
2623                                            and NOS string */
2624
2625                                        /* if these kcallocs fail not much we
2626                                           can do, but better to not fail the
2627                                           sesssetup itself */
2628                                        kfree(ses->serverDomain);
2629                                        ses->serverDomain =
2630                                            kzalloc(2, GFP_KERNEL);
2631                                        kfree(ses->serverNOS);
2632                                        ses->serverNOS =
2633                                            kzalloc(2, GFP_KERNEL);
2634                                }
2635                        } else {        /* ASCII */
2636                                len = strnlen(bcc_ptr, 1024);
2637                                if (((long) bcc_ptr + len) - (long)
2638                                    pByteArea(smb_buffer_response)
2639                                            <= BCC(smb_buffer_response)) {
2640                                        kfree(ses->serverOS);
2641                                        ses->serverOS = kzalloc(len + 1,
2642                                                                GFP_KERNEL);
2643                                        if (ses->serverOS == NULL)
2644                                                goto sesssetup_nomem;
2645                                        strncpy(ses->serverOS, bcc_ptr, len);
2646
2647                                        bcc_ptr += len;
2648                                        /* null terminate the string */
2649                                        bcc_ptr[0] = 0;
2650                                        bcc_ptr++;
2651
2652                                        len = strnlen(bcc_ptr, 1024);
2653                                        kfree(ses->serverNOS);
2654                                        ses->serverNOS = kzalloc(len + 1,
2655                                                                 GFP_KERNEL);
2656                                        if (ses->serverNOS == NULL)
2657                                                goto sesssetup_nomem;
2658                                        strncpy(ses->serverNOS, bcc_ptr, len);
2659                                        bcc_ptr += len;
2660                                        bcc_ptr[0] = 0;
2661                                        bcc_ptr++;
2662
2663                                        len = strnlen(bcc_ptr, 1024);
2664                                        if (ses->serverDomain)
2665                                                kfree(ses->serverDomain);
2666                                        ses->serverDomain = kzalloc(len + 1,
2667                                                                    GFP_KERNEL);
2668                                        if (ses->serverDomain == NULL)
2669                                                goto sesssetup_nomem;
2670                                        strncpy(ses->serverDomain, bcc_ptr,
2671                                                len);
2672                                        bcc_ptr += len;
2673                                        bcc_ptr[0] = 0;
2674                                        bcc_ptr++;
2675                                } else
2676                                        cFYI(1,
2677                                             ("Variable field of length %d "
2678                                                "extends beyond end of smb ",
2679                                              len));
2680                        }
2681                } else {
2682                        cERROR(1,
2683                               (" Security Blob Length extends beyond "
2684                                "end of SMB"));
2685                }
2686        } else {
2687                cERROR(1,
2688                       (" Invalid Word count %d: ",
2689                        smb_buffer_response->WordCount));
2690                rc = -EIO;
2691        }
2692sesssetup_nomem:        /* do not return an error on nomem for the info strings,
2693                           since that could make reconnection harder, and
2694                           reconnection might be needed to free memory */
2695        cifs_buf_release(smb_buffer);
2696
2697        return rc;
2698}
2699
2700static int
2701CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2702                              struct cifsSesInfo *ses, bool *pNTLMv2_flag,
2703                              const struct nls_table *nls_codepage)
2704{
2705        struct smb_hdr *smb_buffer;
2706        struct smb_hdr *smb_buffer_response;
2707        SESSION_SETUP_ANDX *pSMB;
2708        SESSION_SETUP_ANDX *pSMBr;
2709        char *bcc_ptr;
2710        char *domain;
2711        int rc = 0;
2712        int remaining_words = 0;
2713        int bytes_returned = 0;
2714        int len;
2715        int SecurityBlobLength = sizeof(NEGOTIATE_MESSAGE);
2716        PNEGOTIATE_MESSAGE SecurityBlob;
2717        PCHALLENGE_MESSAGE SecurityBlob2;
2718        __u32 negotiate_flags, capabilities;
2719        __u16 count;
2720
2721        cFYI(1, ("In NTLMSSP sesssetup (negotiate)"));
2722        if (ses == NULL)
2723                return -EINVAL;
2724        domain = ses->domainName;
2725        *pNTLMv2_flag = false;
2726        smb_buffer = cifs_buf_get();
2727        if (smb_buffer == NULL) {
2728                return -ENOMEM;
2729        }
2730        smb_buffer_response = smb_buffer;
2731        pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2732        pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2733
2734        /* send SMBsessionSetup here */
2735        header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2736                        NULL /* no tCon exists yet */ , 12 /* wct */ );
2737
2738        smb_buffer->Mid = GetNextMid(ses->server);
2739        pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2740        pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2741
2742        pSMB->req.AndXCommand = 0xFF;
2743        pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2744        pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2745
2746        if (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2747                smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2748
2749        capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2750            CAP_EXTENDED_SECURITY;
2751        if (ses->capabilities & CAP_UNICODE) {
2752                smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2753                capabilities |= CAP_UNICODE;
2754        }
2755        if (ses->capabilities & CAP_STATUS32) {
2756                smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2757                capabilities |= CAP_STATUS32;
2758        }
2759        if (ses->capabilities & CAP_DFS) {
2760                smb_buffer->Flags2 |= SMBFLG2_DFS;
2761                capabilities |= CAP_DFS;
2762        }
2763        pSMB->req.Capabilities = cpu_to_le32(capabilities);
2764
2765        bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2766        SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
2767        strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2768        SecurityBlob->MessageType = NtLmNegotiate;
2769        negotiate_flags =
2770            NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
2771            NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM |
2772            NTLMSSP_NEGOTIATE_56 |
2773            /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
2774        if (sign_CIFS_PDUs)
2775                negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
2776/*        if (ntlmv2_support)
2777                negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;*/
2778        /* setup pointers to domain name and workstation name */
2779        bcc_ptr += SecurityBlobLength;
2780
2781        SecurityBlob->WorkstationName.Buffer = 0;
2782        SecurityBlob->WorkstationName.Length = 0;
2783        SecurityBlob->WorkstationName.MaximumLength = 0;
2784
2785        /* Domain not sent on first Sesssetup in NTLMSSP, instead it is sent
2786        along with username on auth request (ie the response to challenge) */
2787        SecurityBlob->DomainName.Buffer = 0;
2788        SecurityBlob->DomainName.Length = 0;
2789        SecurityBlob->DomainName.MaximumLength = 0;
2790        if (ses->capabilities & CAP_UNICODE) {
2791                if ((long) bcc_ptr % 2) {
2792                        *bcc_ptr = 0;
2793                        bcc_ptr++;
2794                }
2795
2796                bytes_returned =
2797                    cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
2798                                  32, nls_codepage);
2799                bcc_ptr += 2 * bytes_returned;
2800                bytes_returned =
2801                    cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release, 32,
2802                                  nls_codepage);
2803                bcc_ptr += 2 * bytes_returned;
2804                bcc_ptr += 2;        /* null terminate Linux version */
2805                bytes_returned =
2806                    cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
2807                                  64, nls_codepage);
2808                bcc_ptr += 2 * bytes_returned;
2809                *(bcc_ptr + 1) = 0;
2810                *(bcc_ptr + 2) = 0;
2811                bcc_ptr += 2;        /* null terminate network opsys string */
2812                *(bcc_ptr + 1) = 0;
2813                *(bcc_ptr + 2) = 0;
2814                bcc_ptr += 2;        /* null domain */
2815        } else {                /* ASCII */
2816                strcpy(bcc_ptr, "Linux version ");
2817                bcc_ptr += strlen("Linux version ");
2818                strcpy(bcc_ptr, utsname()->release);
2819                bcc_ptr += strlen(utsname()->release) + 1;
2820                strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2821                bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2822                bcc_ptr++;        /* empty domain field */
2823                *bcc_ptr = 0;
2824        }
2825        SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2826        pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2827        count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2828        smb_buffer->smb_buf_length += count;
2829        pSMB->req.ByteCount = cpu_to_le16(count);
2830
2831        rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2832                         &bytes_returned, CIFS_LONG_OP);
2833
2834        if (smb_buffer_response->Status.CifsError ==
2835            cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
2836                rc = 0;
2837
2838        if (rc) {
2839/*    rc = map_smb_to_linux_error(smb_buffer_response);  *//* done in SendReceive now */
2840        } else if ((smb_buffer_response->WordCount == 3)
2841                   || (smb_buffer_response->WordCount == 4)) {
2842                __u16 action = le16_to_cpu(pSMBr->resp.Action);
2843                __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2844
2845                if (action & GUEST_LOGIN)
2846                        cFYI(1, (" Guest login"));
2847        /* Do we want to set anything in SesInfo struct when guest login? */
2848
2849                bcc_ptr = pByteArea(smb_buffer_response);
2850        /* response can have either 3 or 4 word count - Samba sends 3 */
2851
2852                SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
2853                if (SecurityBlob2->MessageType != NtLmChallenge) {
2854                        cFYI(1,
2855                             ("Unexpected NTLMSSP message type received %d",
2856                              SecurityBlob2->MessageType));
2857                } else if (ses) {
2858                        ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
2859                        cFYI(1, ("UID = %d", ses->Suid));
2860                        if ((pSMBr->resp.hdr.WordCount == 3)
2861                            || ((pSMBr->resp.hdr.WordCount == 4)
2862                                && (blob_len <
2863                                    pSMBr->resp.ByteCount))) {
2864
2865                                if (pSMBr->resp.hdr.WordCount == 4) {
2866                                        bcc_ptr += blob_len;
2867                                        cFYI(1, ("Security Blob Length %d",
2868                                              blob_len));
2869                                }
2870
2871                                cFYI(1, ("NTLMSSP Challenge rcvd"));
2872
2873                                memcpy(ses->server->cryptKey,
2874                                       SecurityBlob2->Challenge,
2875                                       CIFS_CRYPTO_KEY_SIZE);
2876                                if (SecurityBlob2->NegotiateFlags &
2877                                        cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
2878                                        *pNTLMv2_flag = true;
2879
2880                                if ((SecurityBlob2->NegotiateFlags &
2881                                        cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN))
2882                                        || (sign_CIFS_PDUs > 1))
2883                                                ses->server->secMode |=
2884                                                        SECMODE_SIGN_REQUIRED;
2885                                if ((SecurityBlob2->NegotiateFlags &
2886                                        cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs))
2887                                                ses->server->secMode |=
2888                                                        SECMODE_SIGN_ENABLED;
2889
2890                                if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2891                                        if ((long) (bcc_ptr) % 2) {
2892                                                remaining_words =
2893                                                    (BCC(smb_buffer_response)
2894                                                     - 1) / 2;
2895                                         /* Must word align unicode strings */
2896                                                bcc_ptr++;
2897                                        } else {
2898                                                remaining_words =
2899                                                    BCC
2900                                                    (smb_buffer_response) / 2;
2901                                        }
2902                                        len =
2903                                            UniStrnlen((wchar_t *) bcc_ptr,
2904                                                       remaining_words - 1);
2905/* We look for obvious messed up bcc or strings in response so we do not go off
2906   the end since (at least) WIN2K and Windows XP have a major bug in not null
2907   terminating last Unicode string in response  */
2908                                        if (ses->serverOS)
2909                                                kfree(ses->serverOS);
2910                                        ses->serverOS =
2911                                            kzalloc(2 * (len + 1), GFP_KERNEL);
2912                                        cifs_strfromUCS_le(ses->serverOS,
2913                                                           (__le16 *)
2914                                                           bcc_ptr, len,
2915                                                           nls_codepage);
2916                                        bcc_ptr += 2 * (len + 1);
2917                                        remaining_words -= len + 1;
2918                                        ses->serverOS[2 * len] = 0;
2919                                        ses->serverOS[1 + (2 * len)] = 0;
2920                                        if (remaining_words > 0) {
2921                                                len = UniStrnlen((wchar_t *)
2922                                                                 bcc_ptr,
2923                                                                 remaining_words
2924                                                                 - 1);
2925                                                kfree(ses->serverNOS);
2926                                                ses->serverNOS =
2927                                                    kzalloc(2 * (len + 1),
2928                                                            GFP_KERNEL);
2929                                                cifs_strfromUCS_le(ses->
2930                                                                   serverNOS,
2931                                                                   (__le16 *)
2932                                                                   bcc_ptr,
2933                                                                   len,
2934                                                                   nls_codepage);
2935                                                bcc_ptr += 2 * (len + 1);
2936                                                ses->serverNOS[2 * len] = 0;
2937                                                ses->serverNOS[1 +
2938                                                               (2 * len)] = 0;
2939                                                remaining_words -= len + 1;
2940                                                if (remaining_words > 0) {
2941                                                        len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2942                                /* last string not always null terminated
2943                                   (for e.g. for Windows XP & 2000) */
2944                                                        kfree(ses->serverDomain);
2945                                                        ses->serverDomain =
2946                                                            kzalloc(2 *
2947                                                                    (len +
2948                                                                     1),
2949                                                                    GFP_KERNEL);
2950                                                        cifs_strfromUCS_le
2951                                                            (ses->serverDomain,
2952                                                             (__le16 *)bcc_ptr,
2953                                                             len, nls_codepage);
2954                                                        bcc_ptr +=
2955                                                            2 * (len + 1);
2956                                                        ses->serverDomain[2*len]
2957                                                            = 0;
2958                                                        ses->serverDomain
2959                                                                [1 + (2 * len)]
2960                                                            = 0;
2961                                                } /* else no more room so create dummy domain string */
2962                                                else {
2963                                                        kfree(ses->serverDomain);
2964                                                        ses->serverDomain =
2965                                                            kzalloc(2,
2966                                                                    GFP_KERNEL);
2967                                                }
2968                                        } else {        /* no room so create dummy domain and NOS string */
2969                                                kfree(ses->serverDomain);
2970                                                ses->serverDomain =
2971                                                    kzalloc(2, GFP_KERNEL);
2972                                                kfree(ses->serverNOS);
2973                                                ses->serverNOS =
2974                                                    kzalloc(2, GFP_KERNEL);
2975                                        }
2976                                } else {        /* ASCII */
2977                                        len = strnlen(bcc_ptr, 1024);
2978                                        if (((long) bcc_ptr + len) - (long)
2979                                            pByteArea(smb_buffer_response)
2980                                            <= BCC(smb_buffer_response)) {
2981                                                if (ses->serverOS)
2982                                                        kfree(ses->serverOS);
2983                                                ses->serverOS =
2984                                                    kzalloc(len + 1,
2985                                                            GFP_KERNEL);
2986                                                strncpy(ses->serverOS,
2987                                                        bcc_ptr, len);
2988
2989                                                bcc_ptr += len;
2990                                                bcc_ptr[0] = 0;        /* null terminate string */
2991                                                bcc_ptr++;
2992
2993                                                len = strnlen(bcc_ptr, 1024);
2994                                                kfree(ses->serverNOS);
2995                                                ses->serverNOS =
2996                                                    kzalloc(len + 1,
2997                                                            GFP_KERNEL);
2998                                                strncpy(ses->serverNOS, bcc_ptr, len);
2999                                                bcc_ptr += len;
3000                                                bcc_ptr[0] = 0;
3001                                                bcc_ptr++;
3002
3003                                                len = strnlen(bcc_ptr, 1024);
3004                                                kfree(ses->serverDomain);
3005                                                ses->serverDomain =
3006                                                    kzalloc(len + 1,
3007                                                            GFP_KERNEL);
3008                                                strncpy(ses->serverDomain,
3009                                                        bcc_ptr, len);
3010                                                bcc_ptr += len;
3011                                                bcc_ptr[0] = 0;
3012                                                bcc_ptr++;
3013                                        } else
3014                                                cFYI(1,
3015                                                     ("field of length %d "
3016                                                    "extends beyond end of smb",
3017                                                      len));
3018                                }
3019                        } else {
3020                                cERROR(1, ("Security Blob Length extends beyond"
3021                                           " end of SMB"));
3022                        }
3023                } else {
3024                        cERROR(1, ("No session structure passed in."));
3025                }
3026        } else {
3027                cERROR(1,
3028                       (" Invalid Word count %d:",
3029                        smb_buffer_response->WordCount));
3030                rc = -EIO;
3031        }
3032
3033        cifs_buf_release(smb_buffer);
3034
3035        return rc;
3036}
3037static int
3038CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
3039                        char *ntlm_session_key, bool ntlmv2_flag,
3040                        const struct nls_table *nls_codepage)
3041{
3042        struct smb_hdr *smb_buffer;
3043        struct smb_hdr *smb_buffer_response;
3044        SESSION_SETUP_ANDX *pSMB;
3045        SESSION_SETUP_ANDX *pSMBr;
3046        char *bcc_ptr;
3047        char *user;
3048        char *domain;
3049        int rc = 0;
3050        int remaining_words = 0;
3051        int bytes_returned = 0;
3052        int len;
3053        int SecurityBlobLength = sizeof(AUTHENTICATE_MESSAGE);
3054        PAUTHENTICATE_MESSAGE SecurityBlob;
3055        __u32 negotiate_flags, capabilities;
3056        __u16 count;
3057
3058        cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
3059        if (ses == NULL)
3060                return -EINVAL;
3061        user = ses->userName;
3062        domain = ses->domainName;
3063        smb_buffer = cifs_buf_get();
3064        if (smb_buffer == NULL) {
3065                return -ENOMEM;
3066        }
3067        smb_buffer_response = smb_buffer;
3068        pSMB = (SESSION_SETUP_ANDX *)smb_buffer;
3069        pSMBr = (SESSION_SETUP_ANDX *)smb_buffer_response;
3070
3071        /* send SMBsessionSetup here */
3072        header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
3073                        NULL /* no tCon exists yet */ , 12 /* wct */ );
3074
3075        smb_buffer->Mid = GetNextMid(ses->server);
3076        pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
3077        pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
3078        pSMB->req.AndXCommand = 0xFF;
3079        pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
3080        pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
3081
3082        pSMB->req.hdr.Uid = ses->Suid;
3083
3084        if (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
3085                smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3086
3087        capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
3088                        CAP_EXTENDED_SECURITY;
3089        if (ses->capabilities & CAP_UNICODE) {
3090                smb_buffer->Flags2 |= SMBFLG2_UNICODE;
3091                capabilities |= CAP_UNICODE;
3092        }
3093        if (ses->capabilities & CAP_STATUS32) {
3094                smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
3095                capabilities |= CAP_STATUS32;
3096        }
3097        if (ses->capabilities & CAP_DFS) {
3098                smb_buffer->Flags2 |= SMBFLG2_DFS;
3099                capabilities |= CAP_DFS;
3100        }
3101        pSMB->req.Capabilities = cpu_to_le32(capabilities);
3102
3103        bcc_ptr = (char *)&pSMB->req.SecurityBlob;
3104        SecurityBlob = (PAUTHENTICATE_MESSAGE)bcc_ptr;
3105        strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
3106        SecurityBlob->MessageType = NtLmAuthenticate;
3107        bcc_ptr += SecurityBlobLength;
3108        negotiate_flags = NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
3109                        NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
3110                        0x80000000 | NTLMSSP_NEGOTIATE_128;
3111        if (sign_CIFS_PDUs)
3112                negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
3113        if (ntlmv2_flag)
3114                negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
3115
3116/* setup pointers to domain name and workstation name */
3117
3118        SecurityBlob->WorkstationName.Buffer = 0;
3119        SecurityBlob->WorkstationName.Length = 0;
3120        SecurityBlob->WorkstationName.MaximumLength = 0;
3121        SecurityBlob->SessionKey.Length = 0;
3122        SecurityBlob->SessionKey.MaximumLength = 0;
3123        SecurityBlob->SessionKey.Buffer = 0;
3124
3125        SecurityBlob->LmChallengeResponse.Length = 0;
3126        SecurityBlob->LmChallengeResponse.MaximumLength = 0;
3127        SecurityBlob->LmChallengeResponse.Buffer = 0;
3128
3129        SecurityBlob->NtChallengeResponse.Length =
3130            cpu_to_le16(CIFS_SESS_KEY_SIZE);
3131        SecurityBlob->NtChallengeResponse.MaximumLength =
3132            cpu_to_le16(CIFS_SESS_KEY_SIZE);
3133        memcpy(bcc_ptr, ntlm_session_key, CIFS_SESS_KEY_SIZE);
3134        SecurityBlob->NtChallengeResponse.Buffer =
3135            cpu_to_le32(SecurityBlobLength);
3136        SecurityBlobLength += CIFS_SESS_KEY_SIZE;
3137        bcc_ptr += CIFS_SESS_KEY_SIZE;
3138
3139        if (ses->capabilities & CAP_UNICODE) {
3140                if (domain == NULL) {
3141                        SecurityBlob->DomainName.Buffer = 0;
3142                        SecurityBlob->DomainName.Length = 0;
3143                        SecurityBlob->DomainName.MaximumLength = 0;
3144                } else {
3145                        __u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
3146                                          nls_codepage);
3147                        ln *= 2;
3148                        SecurityBlob->DomainName.MaximumLength =
3149                            cpu_to_le16(ln);
3150                        SecurityBlob->DomainName.Buffer =
3151                            cpu_to_le32(SecurityBlobLength);
3152                        bcc_ptr += ln;
3153                        SecurityBlobLength += ln;
3154                        SecurityBlob->DomainName.Length = cpu_to_le16(ln);
3155                }
3156                if (user == NULL) {
3157                        SecurityBlob->UserName.Buffer = 0;
3158                        SecurityBlob->UserName.Length = 0;
3159                        SecurityBlob->UserName.MaximumLength = 0;
3160                } else {
3161                        __u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, user, 64,
3162                                          nls_codepage);
3163                        ln *= 2;
3164                        SecurityBlob->UserName.MaximumLength =
3165                            cpu_to_le16(ln);
3166                        SecurityBlob->UserName.Buffer =
3167                            cpu_to_le32(SecurityBlobLength);
3168                        bcc_ptr += ln;
3169                        SecurityBlobLength += ln;
3170                        SecurityBlob->UserName.Length = cpu_to_le16(ln);
3171                }
3172
3173                /* SecurityBlob->WorkstationName.Length =
3174                 cifs_strtoUCS((__le16 *) bcc_ptr, "AMACHINE",64, nls_codepage);
3175                   SecurityBlob->WorkstationName.Length *= 2;
3176                   SecurityBlob->WorkstationName.MaximumLength =
3177                        cpu_to_le16(SecurityBlob->WorkstationName.Length);
3178                   SecurityBlob->WorkstationName.Buffer =
3179                                 cpu_to_le32(SecurityBlobLength);
3180                   bcc_ptr += SecurityBlob->WorkstationName.Length;
3181                   SecurityBlobLength += SecurityBlob->WorkstationName.Length;
3182                   SecurityBlob->WorkstationName.Length =
3183                        cpu_to_le16(SecurityBlob->WorkstationName.Length);  */
3184
3185                if ((long) bcc_ptr % 2) {
3186                        *bcc_ptr = 0;
3187                        bcc_ptr++;
3188                }
3189                bytes_returned =
3190                    cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
3191                                  32, nls_codepage);
3192                bcc_ptr += 2 * bytes_returned;
3193                bytes_returned =
3194                    cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release, 32,
3195                                  nls_codepage);
3196                bcc_ptr += 2 * bytes_returned;
3197                bcc_ptr += 2;        /* null term version string */
3198                bytes_returned =
3199                    cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
3200                                  64, nls_codepage);
3201                bcc_ptr += 2 * bytes_returned;
3202                *(bcc_ptr + 1) = 0;
3203                *(bcc_ptr + 2) = 0;
3204                bcc_ptr += 2;        /* null terminate network opsys string */
3205                *(bcc_ptr + 1) = 0;
3206                *(bcc_ptr + 2) = 0;
3207                bcc_ptr += 2;        /* null domain */
3208        } else {                /* ASCII */
3209                if (domain == NULL) {
3210                        SecurityBlob->DomainName.Buffer = 0;
3211                        SecurityBlob->DomainName.Length = 0;
3212                        SecurityBlob->DomainName.MaximumLength = 0;
3213                } else {
3214                        __u16 ln;
3215                        negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
3216                        strncpy(bcc_ptr, domain, 63);
3217                        ln = strnlen(domain, 64);
3218                        SecurityBlob->DomainName.MaximumLength =
3219                            cpu_to_le16(ln);
3220                        SecurityBlob->DomainName.Buffer =
3221                            cpu_to_le32(SecurityBlobLength);
3222                        bcc_ptr += ln;
3223                        SecurityBlobLength += ln;
3224                        SecurityBlob->DomainName.Length = cpu_to_le16(ln);
3225                }
3226                if (user == NULL) {
3227                        SecurityBlob->UserName.Buffer = 0;
3228                        SecurityBlob->UserName.Length = 0;
3229                        SecurityBlob->UserName.MaximumLength = 0;
3230                } else {
3231                        __u16 ln;
3232                        strncpy(bcc_ptr, user, 63);
3233                        ln = strnlen(user, 64);
3234                        SecurityBlob->UserName.MaximumLength = cpu_to_le16(ln);
3235                        SecurityBlob->UserName.Buffer =
3236                                                cpu_to_le32(SecurityBlobLength);
3237                        bcc_ptr += ln;
3238                        SecurityBlobLength += ln;
3239                        SecurityBlob->UserName.Length = cpu_to_le16(ln);
3240                }
3241                /* BB fill in our workstation name if known BB */
3242
3243                strcpy(bcc_ptr, "Linux version ");
3244                bcc_ptr += strlen("Linux version ");
3245                strcpy(bcc_ptr, utsname()->release);
3246                bcc_ptr += strlen(utsname()->release) + 1;
3247                strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
3248                bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
3249                bcc_ptr++;        /* null domain */
3250                *bcc_ptr = 0;
3251        }
3252        SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
3253        pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
3254        count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
3255        smb_buffer->smb_buf_length += count;
3256        pSMB->req.ByteCount = cpu_to_le16(count);
3257
3258        rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
3259                         &bytes_returned, CIFS_LONG_OP);
3260        if (rc) {
3261/*   rc = map_smb_to_linux_error(smb_buffer_response) done in SendReceive now */
3262        } else if ((smb_buffer_response->WordCount == 3) ||
3263                   (smb_buffer_response->WordCount == 4)) {
3264                __u16 action = le16_to_cpu(pSMBr->resp.Action);
3265                __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
3266                if (action & GUEST_LOGIN)
3267                        cFYI(1, (" Guest login")); /* BB Should we set anything
3268                                                         in SesInfo struct ? */
3269/*                if (SecurityBlob2->MessageType != NtLm??) {
3270                        cFYI("Unexpected message type on auth response is %d"));
3271                } */
3272
3273                if (ses) {
3274                        cFYI(1,
3275                             ("Check challenge UID %d vs auth response UID %d",
3276                              ses->Suid, smb_buffer_response->Uid));
3277                        /* UID left in wire format */
3278                        ses->Suid = smb_buffer_response->Uid;
3279                        bcc_ptr = pByteArea(smb_buffer_response);
3280                /* response can have either 3 or 4 word count - Samba sends 3 */
3281                        if ((pSMBr->resp.hdr.WordCount == 3)
3282                            || ((pSMBr->resp.hdr.WordCount == 4)
3283                                && (blob_len <
3284                                    pSMBr->resp.ByteCount))) {
3285                                if (pSMBr->resp.hdr.WordCount == 4) {
3286                                        bcc_ptr +=
3287                                            blob_len;
3288                                        cFYI(1,
3289                                             ("Security Blob Length %d ",
3290                                              blob_len));
3291                                }
3292
3293                                cFYI(1,
3294                                     ("NTLMSSP response to Authenticate "));
3295
3296                                if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
3297                                        if ((long) (bcc_ptr) % 2) {
3298                                                remaining_words =
3299                                                    (BCC(smb_buffer_response)
3300                                                     - 1) / 2;
3301                                                bcc_ptr++;        /* Unicode strings must be word aligned */
3302                                        } else {
3303                                                remaining_words = BCC(smb_buffer_response) / 2;
3304                                        }
3305                                        len = UniStrnlen((wchar_t *) bcc_ptr,
3306                                                        remaining_words - 1);
3307/* We look for obvious messed up bcc or strings in response so we do not go off
3308  the end since (at least) WIN2K and Windows XP have a major bug in not null
3309  terminating last Unicode string in response  */
3310                                        if (ses->serverOS)
3311                                                kfree(ses->serverOS);
3312                                        ses->serverOS =
3313                                            kzalloc(2 * (len + 1), GFP_KERNEL);
3314                                        cifs_strfromUCS_le(ses->serverOS,
3315                                                           (__le16 *)
3316                                                           bcc_ptr, len,
3317                                                           nls_codepage);
3318                                        bcc_ptr += 2 * (len + 1);
3319                                        remaining_words -= len + 1;
3320                                        ses->serverOS[2 * len] = 0;
3321                                        ses->serverOS[1 + (2 * len)] = 0;
3322                                        if (remaining_words > 0) {
3323                                                len = UniStrnlen((wchar_t *)
3324                                                                 bcc_ptr,
3325                                                                 remaining_words
3326                                                                 - 1);
3327                                                kfree(ses->serverNOS);
3328                                                ses->serverNOS =
3329                                                    kzalloc(2 * (len + 1),
3330                                                            GFP_KERNEL);
3331                                                cifs_strfromUCS_le(ses->
3332                                                                   serverNOS,
3333                                                                   (__le16 *)
3334                                                                   bcc_ptr,
3335                                                                   len,
3336                                                                   nls_codepage);
3337                                                bcc_ptr += 2 * (len + 1);
3338                                                ses->serverNOS[2 * len] = 0;
3339                                                ses->serverNOS[1+(2*len)] = 0;
3340                                                remaining_words -= len + 1;
3341                                                if (remaining_words > 0) {
3342                                                        len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
3343     /* last string not always null terminated (e.g. for Windows XP & 2000) */
3344                                                        if (ses->serverDomain)
3345                                                                kfree(ses->serverDomain);
3346                                                        ses->serverDomain =
3347                                                            kzalloc(2 *
3348                                                                    (len +
3349                                                                     1),
3350                                                                    GFP_KERNEL);
3351                                                        cifs_strfromUCS_le
3352                                                            (ses->
3353                                                             serverDomain,
3354                                                             (__le16 *)
3355                                                             bcc_ptr, len,
3356                                                             nls_codepage);
3357                                                        bcc_ptr +=
3358                                                            2 * (len + 1);
3359                                                        ses->
3360                                                            serverDomain[2
3361                                                                         * len]
3362                                                            = 0;
3363                                                        ses->
3364                                                            serverDomain[1
3365                                                                         +
3366                                                                         (2
3367                                                                          *
3368                                                                          len)]
3369                                                            = 0;
3370                                                } /* else no more room so create dummy domain string */
3371                                                else {
3372                                                        if (ses->serverDomain)
3373                                                                kfree(ses->serverDomain);
3374                                                        ses->serverDomain = kzalloc(2,GFP_KERNEL);
3375                                                }
3376                                        } else {  /* no room so create dummy domain and NOS string */
3377                                                if (ses->serverDomain)
3378                                                        kfree(ses->serverDomain);
3379                                                ses->serverDomain = kzalloc(2, GFP_KERNEL);
3380                                                kfree(ses->serverNOS);
3381                                                ses->serverNOS = kzalloc(2, GFP_KERNEL);
3382                                        }
3383                                } else {        /* ASCII */
3384                                        len = strnlen(bcc_ptr, 1024);
3385                                        if (((long) bcc_ptr + len) -
3386                                           (long) pByteArea(smb_buffer_response)
3387                                                <= BCC(smb_buffer_response)) {
3388                                                if (ses->serverOS)
3389                                                        kfree(ses->serverOS);
3390                                                ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
3391                                                strncpy(ses->serverOS,bcc_ptr, len);
3392
3393                                                bcc_ptr += len;
3394                                                bcc_ptr[0] = 0;        /* null terminate the string */
3395                                                bcc_ptr++;
3396
3397                                                len = strnlen(bcc_ptr, 1024);
3398                                                kfree(ses->serverNOS);
3399                                                ses->serverNOS = kzalloc(len+1,
3400                                                                    GFP_KERNEL);
3401                                                strncpy(ses->serverNOS,
3402                                                        bcc_ptr, len);
3403                                                bcc_ptr += len;
3404                                                bcc_ptr[0] = 0;
3405                                                bcc_ptr++;
3406
3407                                                len = strnlen(bcc_ptr, 1024);
3408                                                if (ses->serverDomain)
3409                                                        kfree(ses->serverDomain);
3410                                                ses->serverDomain =
3411                                                                kzalloc(len+1,
3412                                                                    GFP_KERNEL);
3413                                                strncpy(ses->serverDomain,
3414                                                        bcc_ptr, len);
3415                                                bcc_ptr += len;
3416                                                bcc_ptr[0] = 0;
3417                                                bcc_ptr++;
3418                                        } else
3419                                                cFYI(1, ("field of length %d "
3420                                                   "extends beyond end of smb ",
3421                                                      len));
3422                                }
3423                        } else {
3424                                cERROR(1, ("Security Blob extends beyond end "
3425                                        "of SMB"));
3426                        }
3427                } else {
3428                        cERROR(1, ("No session structure passed in."));
3429                }
3430        } else {
3431                cERROR(1, ("Invalid Word count %d: ",
3432                        smb_buffer_response->WordCount));
3433                rc = -EIO;
3434        }
3435
3436        cifs_buf_release(smb_buffer);
3437
3438        return rc;
3439}
3440
3441int
3442CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3443         const char *tree, struct cifsTconInfo *tcon,
3444         const struct nls_table *nls_codepage)
3445{
3446        struct smb_hdr *smb_buffer;
3447        struct smb_hdr *smb_buffer_response;
3448        TCONX_REQ *pSMB;
3449        TCONX_RSP *pSMBr;
3450        unsigned char *bcc_ptr;
3451        int rc = 0;
3452        int length;
3453        __u16 count;
3454
3455        if (ses == NULL)
3456                return -EIO;
3457
3458        smb_buffer = cifs_buf_get();
3459        if (smb_buffer == NULL) {
3460                return -ENOMEM;
3461        }
3462        smb_buffer_response = smb_buffer;
3463
3464        header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
3465                        NULL /*no tid */ , 4 /*wct */ );
3466
3467        smb_buffer->Mid = GetNextMid(ses->server);
3468        smb_buffer->Uid = ses->Suid;
3469        pSMB = (TCONX_REQ *) smb_buffer;
3470        pSMBr = (TCONX_RSP *) smb_buffer_response;
3471
3472        pSMB->AndXCommand = 0xFF;
3473        pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
3474        bcc_ptr = &pSMB->Password[0];
3475        if ((ses->server->secMode) & SECMODE_USER) {
3476                pSMB->PasswordLength = cpu_to_le16(1);        /* minimum */
3477                *bcc_ptr = 0; /* password is null byte */
3478                bcc_ptr++;              /* skip password */
3479                /* already aligned so no need to do it below */
3480        } else {
3481                pSMB->PasswordLength = cpu_to_le16(CIFS_SESS_KEY_SIZE);
3482                /* BB FIXME add code to fail this if NTLMv2 or Kerberos
3483                   specified as required (when that support is added to
3484                   the vfs in the future) as only NTLM or the much
3485                   weaker LANMAN (which we do not send by default) is accepted
3486                   by Samba (not sure whether other servers allow
3487                   NTLMv2 password here) */
3488#ifdef CONFIG_CIFS_WEAK_PW_HASH
3489                if ((extended_security & CIFSSEC_MAY_LANMAN) &&
3490                        (ses->server->secType == LANMAN))
3491                        calc_lanman_hash(ses, bcc_ptr);
3492                else
3493#endif /* CIFS_WEAK_PW_HASH */
3494                SMBNTencrypt(ses->password,
3495                             ses->server->cryptKey,
3496                             bcc_ptr);
3497
3498                bcc_ptr += CIFS_SESS_KEY_SIZE;
3499                if (ses->capabilities & CAP_UNICODE) {
3500                        /* must align unicode strings */
3501                        *bcc_ptr = 0; /* null byte password */
3502                        bcc_ptr++;
3503                }
3504        }
3505
3506        if (ses->server->secMode &
3507                        (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
3508                smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3509
3510        if (ses->capabilities & CAP_STATUS32) {
3511                smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
3512        }
3513        if (ses->capabilities & CAP_DFS) {
3514                smb_buffer->Flags2 |= SMBFLG2_DFS;
3515        }
3516        if (ses->capabilities & CAP_UNICODE) {
3517                smb_buffer->Flags2 |= SMBFLG2_UNICODE;
3518                length =
3519                    cifs_strtoUCS((__le16 *) bcc_ptr, tree,
3520                        6 /* max utf8 char length in bytes */ *
3521                        (/* server len*/ + 256 /* share len */), nls_codepage);
3522                bcc_ptr += 2 * length;        /* convert num 16 bit words to bytes */
3523                bcc_ptr += 2;        /* skip trailing null */
3524        } else {                /* ASCII */
3525                strcpy(bcc_ptr, tree);
3526                bcc_ptr += strlen(tree) + 1;
3527        }
3528        strcpy(bcc_ptr, "?????");
3529        bcc_ptr += strlen("?????");
3530        bcc_ptr += 1;
3531        count = bcc_ptr - &pSMB->Password[0];
3532        pSMB->hdr.smb_buf_length += count;
3533        pSMB->ByteCount = cpu_to_le16(count);
3534
3535        rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
3536                         CIFS_STD_OP);
3537
3538        /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
3539        /* above now done in SendReceive */
3540        if ((rc == 0) && (tcon != NULL)) {
3541                tcon->tidStatus = CifsGood;
3542                tcon->need_reconnect = false;
3543                tcon->tid = smb_buffer_response->Tid;
3544                bcc_ptr = pByteArea(smb_buffer_response);
3545                length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
3546                /* skip service field (NB: this field is always ASCII) */
3547                if (length == 3) {
3548                        if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
3549                            (bcc_ptr[2] == 'C')) {
3550                                cFYI(1, ("IPC connection"));
3551                                tcon->ipc = 1;
3552                        }
3553                } else if (length == 2) {
3554                        if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
3555                                /* the most common case */
3556                                cFYI(1, ("disk share connection"));
3557                        }
3558                }
3559                bcc_ptr += length + 1;
3560                strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
3561                if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
3562                        length = UniStrnlen((wchar_t *) bcc_ptr, 512);
3563                        if ((bcc_ptr + (2 * length)) -
3564                             pByteArea(smb_buffer_response) <=
3565                            BCC(smb_buffer_response)) {
3566                                kfree(tcon->nativeFileSystem);
3567                                tcon->nativeFileSystem =
3568                                    kzalloc(length + 2, GFP_KERNEL);
3569                                if (tcon->nativeFileSystem)
3570                                        cifs_strfromUCS_le(
3571                                                tcon->nativeFileSystem,
3572                                                (__le16 *) bcc_ptr,
3573                                                length, nls_codepage);
3574                                bcc_ptr += 2 * length;
3575                                bcc_ptr[0] = 0;        /* null terminate the string */
3576                                bcc_ptr[1] = 0;
3577                                bcc_ptr += 2;
3578                        }
3579                        /* else do not bother copying these information fields*/
3580                } else {
3581                        length = strnlen(bcc_ptr, 1024);
3582                        if ((bcc_ptr + length) -
3583                            pByteArea(smb_buffer_response) <=
3584                            BCC(smb_buffer_response)) {
3585                                kfree(tcon->nativeFileSystem);
3586                                tcon->nativeFileSystem =
3587                                    kzalloc(length + 1, GFP_KERNEL);
3588                                if (tcon->nativeFileSystem)
3589                                        strncpy(tcon->nativeFileSystem, bcc_ptr,
3590                                                length);
3591                        }
3592                        /* else do not bother copying these information fields*/
3593                }
3594                if ((smb_buffer_response->WordCount == 3) ||
3595                         (smb_buffer_response->WordCount == 7))
3596                        /* field is in same location */
3597                        tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
3598                else
3599                        tcon->Flags = 0;
3600                cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
3601        } else if ((rc == 0) && tcon == NULL) {
3602                /* all we need to save for IPC$ connection */
3603                ses->ipc_tid = smb_buffer_response->Tid;
3604        }
3605
3606        cifs_buf_release(smb_buffer);
3607        return rc;
3608}
3609
3610int
3611cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
3612{
3613        int rc = 0;
3614        char *tmp;
3615
3616        if (cifs_sb->tcon)
3617                cifs_put_tcon(cifs_sb->tcon);
3618
3619        cifs_sb->tcon = NULL;
3620        tmp = cifs_sb->prepath;
3621        cifs_sb->prepathlen = 0;
3622        cifs_sb->prepath = NULL;
3623        kfree(tmp);
3624
3625        return rc;
3626}
3627
3628int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3629                                           struct nls_table *nls_info)
3630{
3631        int rc = 0;
3632        char ntlm_session_key[CIFS_SESS_KEY_SIZE];
3633        bool ntlmv2_flag = false;
3634        int first_time = 0;
3635        struct TCP_Server_Info *server = pSesInfo->server;
3636
3637        /* what if server changes its buffer size after dropping the session? */
3638        if (server->maxBuf == 0) /* no need to send on reconnect */ {
3639                rc = CIFSSMBNegotiate(xid, pSesInfo);
3640                if (rc == -EAGAIN) {
3641                        /* retry only once on 1st time connection */
3642                        rc = CIFSSMBNegotiate(xid, pSesInfo);
3643                        if (rc == -EAGAIN)
3644                                rc = -EHOSTDOWN;
3645                }
3646                if (rc == 0) {
3647                        spin_lock(&GlobalMid_Lock);
3648                        if (server->tcpStatus != CifsExiting)
3649                                server->tcpStatus = CifsGood;
3650                        else
3651                                rc = -EHOSTDOWN;
3652                        spin_unlock(&GlobalMid_Lock);
3653
3654                }
3655                first_time = 1;
3656        }
3657
3658        if (rc)
3659                goto ss_err_exit;
3660
3661        pSesInfo->flags = 0;
3662        pSesInfo->capabilities = server->capabilities;
3663        if (linuxExtEnabled == 0)
3664                pSesInfo->capabilities &= (~CAP_UNIX);
3665        /*        pSesInfo->sequence_number = 0;*/
3666        cFYI(1, ("Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d",
3667                 server->secMode, server->capabilities, server->timeAdj));
3668
3669        if (experimEnabled < 2)
3670                rc = CIFS_SessSetup(xid, pSesInfo, first_time, nls_info);
3671        else if (extended_security
3672                        && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3673                        && (server->secType == NTLMSSP)) {
3674                rc = -EOPNOTSUPP;
3675        } else if (extended_security
3676                        && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3677                        && (server->secType == RawNTLMSSP)) {
3678                cFYI(1, ("NTLMSSP sesssetup"));
3679                rc = CIFSNTLMSSPNegotiateSessSetup(xid, pSesInfo, &ntlmv2_flag,
3680                                                   nls_info);
3681                if (!rc) {
3682                        if (ntlmv2_flag) {
3683                                char *v2_response;
3684                                cFYI(1, ("more secure NTLM ver2 hash"));
3685                                if (CalcNTLMv2_partial_mac_key(pSesInfo,
3686                                                                nls_info)) {
3687                                        rc = -ENOMEM;
3688                                        goto ss_err_exit;
3689                                } else
3690                                        v2_response = kmalloc(16 + 64 /* blob*/,
3691                                                                GFP_KERNEL);
3692                                if (v2_response) {
3693                                        CalcNTLMv2_response(pSesInfo,
3694                                                                v2_response);
3695                                /*        if (first_time)
3696                                                cifs_calculate_ntlmv2_mac_key */
3697                                        kfree(v2_response);
3698                                        /* BB Put dummy sig in SessSetup PDU? */
3699                                } else {
3700                                        rc = -ENOMEM;
3701                                        goto ss_err_exit;
3702                                }
3703
3704                        } else {
3705                                SMBNTencrypt(pSesInfo->password,
3706                                             server->cryptKey,
3707                                             ntlm_session_key);
3708
3709                                if (first_time)
3710                                        cifs_calculate_mac_key(
3711                                             &server->mac_signing_key,
3712                                             ntlm_session_key,
3713                                             pSesInfo->password);
3714                        }
3715                        /* for better security the weaker lanman hash not sent
3716                           in AuthSessSetup so we no longer calculate it */
3717
3718                        rc = CIFSNTLMSSPAuthSessSetup(xid, pSesInfo,
3719                                                      ntlm_session_key,
3720                                                      ntlmv2_flag,
3721                                                      nls_info);
3722                }
3723        } else { /* old style NTLM 0.12 session setup */
3724                SMBNTencrypt(pSesInfo->password, server->cryptKey,
3725                             ntlm_session_key);
3726
3727                if (first_time)
3728                        cifs_calculate_mac_key(&server->mac_signing_key,
3729                                                ntlm_session_key,
3730                                                pSesInfo->password);
3731
3732                rc = CIFSSessSetup(xid, pSesInfo, ntlm_session_key, nls_info);
3733        }
3734        if (rc) {
3735                cERROR(1, ("Send error in SessSetup = %d", rc));
3736        } else {
3737                cFYI(1, ("CIFS Session Established successfully"));
3738                        spin_lock(&GlobalMid_Lock);
3739                        pSesInfo->status = CifsGood;
3740                        pSesInfo->need_reconnect = false;
3741                        spin_unlock(&GlobalMid_Lock);
3742        }
3743
3744ss_err_exit:
3745        return rc;
3746}
3747