linux/fs/cifs/smb2pdu.c
<<
>>
Prefs
   1/*
   2 *   fs/cifs/smb2pdu.c
   3 *
   4 *   Copyright (C) International Business Machines  Corp., 2009, 2011
   5 *                 Etersoft, 2012
   6 *   Author(s): Steve French (sfrench@us.ibm.com)
   7 *              Pavel Shilovsky (pshilovsky@samba.org) 2012
   8 *
   9 *   Contains the routines for constructing the SMB2 PDUs themselves
  10 *
  11 *   This library is free software; you can redistribute it and/or modify
  12 *   it under the terms of the GNU Lesser General Public License as published
  13 *   by the Free Software Foundation; either version 2.1 of the License, or
  14 *   (at your option) any later version.
  15 *
  16 *   This library is distributed in the hope that it will be useful,
  17 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  18 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
  19 *   the GNU Lesser General Public License for more details.
  20 *
  21 *   You should have received a copy of the GNU Lesser General Public License
  22 *   along with this library; if not, write to the Free Software
  23 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  24 */
  25
  26 /* SMB2 PDU handling routines here - except for leftovers (eg session setup) */
  27 /* Note that there are handle based routines which must be                   */
  28 /* treated slightly differently for reconnection purposes since we never     */
  29 /* want to reuse a stale file handle and only the caller knows the file info */
  30
  31#include <linux/fs.h>
  32#include <linux/kernel.h>
  33#include <linux/vfs.h>
  34#include <linux/uaccess.h>
  35#include <linux/xattr.h>
  36#include "smb2pdu.h"
  37#include "cifsglob.h"
  38#include "cifsacl.h"
  39#include "cifsproto.h"
  40#include "smb2proto.h"
  41#include "cifs_unicode.h"
  42#include "cifs_debug.h"
  43#include "ntlmssp.h"
  44#include "smb2status.h"
  45
  46/*
  47 *  The following table defines the expected "StructureSize" of SMB2 requests
  48 *  in order by SMB2 command.  This is similar to "wct" in SMB/CIFS requests.
  49 *
  50 *  Note that commands are defined in smb2pdu.h in le16 but the array below is
  51 *  indexed by command in host byte order.
  52 */
  53static const int smb2_req_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = {
  54        /* SMB2_NEGOTIATE */ 36,
  55        /* SMB2_SESSION_SETUP */ 25,
  56        /* SMB2_LOGOFF */ 4,
  57        /* SMB2_TREE_CONNECT */ 9,
  58        /* SMB2_TREE_DISCONNECT */ 4,
  59        /* SMB2_CREATE */ 57,
  60        /* SMB2_CLOSE */ 24,
  61        /* SMB2_FLUSH */ 24,
  62        /* SMB2_READ */ 49,
  63        /* SMB2_WRITE */ 49,
  64        /* SMB2_LOCK */ 48,
  65        /* SMB2_IOCTL */ 57,
  66        /* SMB2_CANCEL */ 4,
  67        /* SMB2_ECHO */ 4,
  68        /* SMB2_QUERY_DIRECTORY */ 33,
  69        /* SMB2_CHANGE_NOTIFY */ 32,
  70        /* SMB2_QUERY_INFO */ 41,
  71        /* SMB2_SET_INFO */ 33,
  72        /* SMB2_OPLOCK_BREAK */ 24 /* BB this is 36 for LEASE_BREAK variant */
  73};
  74
  75
  76static void
  77smb2_hdr_assemble(struct smb2_hdr *hdr, __le16 smb2_cmd /* command */ ,
  78                  const struct cifs_tcon *tcon)
  79{
  80        struct smb2_pdu *pdu = (struct smb2_pdu *)hdr;
  81        char *temp = (char *)hdr;
  82        /* lookup word count ie StructureSize from table */
  83        __u16 parmsize = smb2_req_struct_sizes[le16_to_cpu(smb2_cmd)];
  84
  85        /*
  86         * smaller than SMALL_BUFFER_SIZE but bigger than fixed area of
  87         * largest operations (Create)
  88         */
  89        memset(temp, 0, 256);
  90
  91        /* Note this is only network field converted to big endian */
  92        hdr->smb2_buf_length = cpu_to_be32(parmsize + sizeof(struct smb2_hdr)
  93                        - 4 /*  RFC 1001 length field itself not counted */);
  94
  95        hdr->ProtocolId[0] = 0xFE;
  96        hdr->ProtocolId[1] = 'S';
  97        hdr->ProtocolId[2] = 'M';
  98        hdr->ProtocolId[3] = 'B';
  99        hdr->StructureSize = cpu_to_le16(64);
 100        hdr->Command = smb2_cmd;
 101        hdr->CreditRequest = cpu_to_le16(2); /* BB make this dynamic */
 102        hdr->ProcessId = cpu_to_le32((__u16)current->tgid);
 103
 104        if (!tcon)
 105                goto out;
 106
 107        hdr->TreeId = tcon->tid;
 108        /* Uid is not converted */
 109        if (tcon->ses)
 110                hdr->SessionId = tcon->ses->Suid;
 111        /* BB check following DFS flags BB */
 112        /* BB do we have to add check for SHI1005_FLAGS_DFS_ROOT too? */
 113        if (tcon->share_flags & SHI1005_FLAGS_DFS)
 114                hdr->Flags |= SMB2_FLAGS_DFS_OPERATIONS;
 115        /* BB how does SMB2 do case sensitive? */
 116        /* if (tcon->nocase)
 117                hdr->Flags |= SMBFLG_CASELESS; */
 118        /* if (tcon->ses && tcon->ses->server &&
 119            (tcon->ses->server->sec_mode & SECMODE_SIGN_REQUIRED))
 120                hdr->Flags |= SMB2_FLAGS_SIGNED; */
 121out:
 122        pdu->StructureSize2 = cpu_to_le16(parmsize);
 123        return;
 124}
 125
 126static int
 127smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon)
 128{
 129        int rc = 0;
 130        struct nls_table *nls_codepage;
 131        struct cifs_ses *ses;
 132        struct TCP_Server_Info *server;
 133
 134        /*
 135         * SMB2s NegProt, SessSetup, Logoff do not have tcon yet so
 136         * check for tcp and smb session status done differently
 137         * for those three - in the calling routine.
 138         */
 139        if (tcon == NULL)
 140                return rc;
 141
 142        if (smb2_command == SMB2_TREE_CONNECT)
 143                return rc;
 144
 145        if (tcon->tidStatus == CifsExiting) {
 146                /*
 147                 * only tree disconnect, open, and write,
 148                 * (and ulogoff which does not have tcon)
 149                 * are allowed as we start force umount.
 150                 */
 151                if ((smb2_command != SMB2_WRITE) &&
 152                   (smb2_command != SMB2_CREATE) &&
 153                   (smb2_command != SMB2_TREE_DISCONNECT)) {
 154                        cFYI(1, "can not send cmd %d while umounting",
 155                                smb2_command);
 156                        return -ENODEV;
 157                }
 158        }
 159        if ((!tcon->ses) || (tcon->ses->status == CifsExiting) ||
 160            (!tcon->ses->server))
 161                return -EIO;
 162
 163        ses = tcon->ses;
 164        server = ses->server;
 165
 166        /*
 167         * Give demultiplex thread up to 10 seconds to reconnect, should be
 168         * greater than cifs socket timeout which is 7 seconds
 169         */
 170        while (server->tcpStatus == CifsNeedReconnect) {
 171                /*
 172                 * Return to caller for TREE_DISCONNECT and LOGOFF and CLOSE
 173                 * here since they are implicitly done when session drops.
 174                 */
 175                switch (smb2_command) {
 176                /*
 177                 * BB Should we keep oplock break and add flush to exceptions?
 178                 */
 179                case SMB2_TREE_DISCONNECT:
 180                case SMB2_CANCEL:
 181                case SMB2_CLOSE:
 182                case SMB2_OPLOCK_BREAK:
 183                        return -EAGAIN;
 184                }
 185
 186                wait_event_interruptible_timeout(server->response_q,
 187                        (server->tcpStatus != CifsNeedReconnect), 10 * HZ);
 188
 189                /* are we still trying to reconnect? */
 190                if (server->tcpStatus != CifsNeedReconnect)
 191                        break;
 192
 193                /*
 194                 * on "soft" mounts we wait once. Hard mounts keep
 195                 * retrying until process is killed or server comes
 196                 * back on-line
 197                 */
 198                if (!tcon->retry) {
 199                        cFYI(1, "gave up waiting on reconnect in smb_init");
 200                        return -EHOSTDOWN;
 201                }
 202        }
 203
 204        if (!tcon->ses->need_reconnect && !tcon->need_reconnect)
 205                return rc;
 206
 207        nls_codepage = load_nls_default();
 208
 209        /*
 210         * need to prevent multiple threads trying to simultaneously reconnect
 211         * the same SMB session
 212         */
 213        mutex_lock(&tcon->ses->session_mutex);
 214        rc = cifs_negotiate_protocol(0, tcon->ses);
 215        if (!rc && tcon->ses->need_reconnect)
 216                rc = cifs_setup_session(0, tcon->ses, nls_codepage);
 217
 218        if (rc || !tcon->need_reconnect) {
 219                mutex_unlock(&tcon->ses->session_mutex);
 220                goto out;
 221        }
 222
 223        cifs_mark_open_files_invalid(tcon);
 224        rc = SMB2_tcon(0, tcon->ses, tcon->treeName, tcon, nls_codepage);
 225        mutex_unlock(&tcon->ses->session_mutex);
 226        cFYI(1, "reconnect tcon rc = %d", rc);
 227        if (rc)
 228                goto out;
 229        atomic_inc(&tconInfoReconnectCount);
 230        /*
 231         * BB FIXME add code to check if wsize needs update due to negotiated
 232         * smb buffer size shrinking.
 233         */
 234out:
 235        /*
 236         * Check if handle based operation so we know whether we can continue
 237         * or not without returning to caller to reset file handle.
 238         */
 239        /*
 240         * BB Is flush done by server on drop of tcp session? Should we special
 241         * case it and skip above?
 242         */
 243        switch (smb2_command) {
 244        case SMB2_FLUSH:
 245        case SMB2_READ:
 246        case SMB2_WRITE:
 247        case SMB2_LOCK:
 248        case SMB2_IOCTL:
 249        case SMB2_QUERY_DIRECTORY:
 250        case SMB2_CHANGE_NOTIFY:
 251        case SMB2_QUERY_INFO:
 252        case SMB2_SET_INFO:
 253                return -EAGAIN;
 254        }
 255        unload_nls(nls_codepage);
 256        return rc;
 257}
 258
 259/*
 260 * Allocate and return pointer to an SMB request hdr, and set basic
 261 * SMB information in the SMB header. If the return code is zero, this
 262 * function must have filled in request_buf pointer.
 263 */
 264static int
 265small_smb2_init(__le16 smb2_command, struct cifs_tcon *tcon,
 266                void **request_buf)
 267{
 268        int rc = 0;
 269
 270        rc = smb2_reconnect(smb2_command, tcon);
 271        if (rc)
 272                return rc;
 273
 274        /* BB eventually switch this to SMB2 specific small buf size */
 275        *request_buf = cifs_small_buf_get();
 276        if (*request_buf == NULL) {
 277                /* BB should we add a retry in here if not a writepage? */
 278                return -ENOMEM;
 279        }
 280
 281        smb2_hdr_assemble((struct smb2_hdr *) *request_buf, smb2_command, tcon);
 282
 283        if (tcon != NULL) {
 284#ifdef CONFIG_CIFS_STATS2
 285                uint16_t com_code = le16_to_cpu(smb2_command);
 286                cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_sent[com_code]);
 287#endif
 288                cifs_stats_inc(&tcon->num_smbs_sent);
 289        }
 290
 291        return rc;
 292}
 293
 294static void
 295free_rsp_buf(int resp_buftype, void *rsp)
 296{
 297        if (resp_buftype == CIFS_SMALL_BUFFER)
 298                cifs_small_buf_release(rsp);
 299        else if (resp_buftype == CIFS_LARGE_BUFFER)
 300                cifs_buf_release(rsp);
 301}
 302
 303#define SMB2_NUM_PROT 1
 304
 305#define SMB2_PROT   0
 306#define SMB21_PROT  1
 307#define BAD_PROT 0xFFFF
 308
 309#define SMB2_PROT_ID  0x0202
 310#define SMB21_PROT_ID 0x0210
 311#define BAD_PROT_ID   0xFFFF
 312
 313static struct {
 314        int index;
 315        __le16 name;
 316} smb2protocols[] = {
 317        {SMB2_PROT,  cpu_to_le16(SMB2_PROT_ID)},
 318        {SMB21_PROT, cpu_to_le16(SMB21_PROT_ID)},
 319        {BAD_PROT,   cpu_to_le16(BAD_PROT_ID)}
 320};
 321
 322/*
 323 *
 324 *      SMB2 Worker functions follow:
 325 *
 326 *      The general structure of the worker functions is:
 327 *      1) Call smb2_init (assembles SMB2 header)
 328 *      2) Initialize SMB2 command specific fields in fixed length area of SMB
 329 *      3) Call smb_sendrcv2 (sends request on socket and waits for response)
 330 *      4) Decode SMB2 command specific fields in the fixed length area
 331 *      5) Decode variable length data area (if any for this SMB2 command type)
 332 *      6) Call free smb buffer
 333 *      7) return
 334 *
 335 */
 336
 337int
 338SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
 339{
 340        struct smb2_negotiate_req *req;
 341        struct smb2_negotiate_rsp *rsp;
 342        struct kvec iov[1];
 343        int rc = 0;
 344        int resp_buftype;
 345        struct TCP_Server_Info *server;
 346        unsigned int sec_flags;
 347        u16 i;
 348        u16 temp = 0;
 349        int blob_offset, blob_length;
 350        char *security_blob;
 351        int flags = CIFS_NEG_OP;
 352
 353        cFYI(1, "Negotiate protocol");
 354
 355        if (ses->server)
 356                server = ses->server;
 357        else {
 358                rc = -EIO;
 359                return rc;
 360        }
 361
 362        rc = small_smb2_init(SMB2_NEGOTIATE, NULL, (void **) &req);
 363        if (rc)
 364                return rc;
 365
 366        /* if any of auth flags (ie not sign or seal) are overriden use them */
 367        if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
 368                sec_flags = ses->overrideSecFlg;  /* BB FIXME fix sign flags?*/
 369        else /* if override flags set only sign/seal OR them with global auth */
 370                sec_flags = global_secflags | ses->overrideSecFlg;
 371
 372        cFYI(1, "sec_flags 0x%x", sec_flags);
 373
 374        req->hdr.SessionId = 0;
 375
 376        for (i = 0; i < SMB2_NUM_PROT; i++)
 377                req->Dialects[i] = smb2protocols[i].name;
 378
 379        req->DialectCount = cpu_to_le16(i);
 380        inc_rfc1001_len(req, i * 2);
 381
 382        /* only one of SMB2 signing flags may be set in SMB2 request */
 383        if ((sec_flags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN)
 384                temp = SMB2_NEGOTIATE_SIGNING_REQUIRED;
 385        else if (sec_flags & CIFSSEC_MAY_SIGN) /* MAY_SIGN is a single flag */
 386                temp = SMB2_NEGOTIATE_SIGNING_ENABLED;
 387
 388        req->SecurityMode = cpu_to_le16(temp);
 389
 390        req->Capabilities = cpu_to_le32(SMB2_GLOBAL_CAP_DFS);
 391
 392        iov[0].iov_base = (char *)req;
 393        /* 4 for rfc1002 length field */
 394        iov[0].iov_len = get_rfc1002_length(req) + 4;
 395
 396        rc = SendReceive2(xid, ses, iov, 1, &resp_buftype, flags);
 397
 398        rsp = (struct smb2_negotiate_rsp *)iov[0].iov_base;
 399        /*
 400         * No tcon so can't do
 401         * cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[SMB2...]);
 402         */
 403        if (rc != 0)
 404                goto neg_exit;
 405
 406        if (rsp == NULL) {
 407                rc = -EIO;
 408                goto neg_exit;
 409        }
 410
 411        cFYI(1, "mode 0x%x", rsp->SecurityMode);
 412
 413        if (rsp->DialectRevision == smb2protocols[SMB21_PROT].name)
 414                cFYI(1, "negotiated smb2.1 dialect");
 415        else if (rsp->DialectRevision == smb2protocols[SMB2_PROT].name)
 416                cFYI(1, "negotiated smb2 dialect");
 417        else {
 418                cERROR(1, "Illegal dialect returned by server %d",
 419                           le16_to_cpu(rsp->DialectRevision));
 420                rc = -EIO;
 421                goto neg_exit;
 422        }
 423        server->dialect = le16_to_cpu(rsp->DialectRevision);
 424
 425        server->maxBuf = le32_to_cpu(rsp->MaxTransactSize);
 426        server->max_read = le32_to_cpu(rsp->MaxReadSize);
 427        server->max_write = le32_to_cpu(rsp->MaxWriteSize);
 428        /* BB Do we need to validate the SecurityMode? */
 429        server->sec_mode = le16_to_cpu(rsp->SecurityMode);
 430        server->capabilities = le32_to_cpu(rsp->Capabilities);
 431        /* Internal types */
 432        server->capabilities |= SMB2_NT_FIND | SMB2_LARGE_FILES;
 433
 434        security_blob = smb2_get_data_area_len(&blob_offset, &blob_length,
 435                                               &rsp->hdr);
 436        if (blob_length == 0) {
 437                cERROR(1, "missing security blob on negprot");
 438                rc = -EIO;
 439                goto neg_exit;
 440        }
 441#ifdef CONFIG_SMB2_ASN1  /* BB REMOVEME when updated asn1.c ready */
 442        rc = decode_neg_token_init(security_blob, blob_length,
 443                                   &server->sec_type);
 444        if (rc == 1)
 445                rc = 0;
 446        else if (rc == 0) {
 447                rc = -EIO;
 448                goto neg_exit;
 449        }
 450#endif
 451
 452neg_exit:
 453        free_rsp_buf(resp_buftype, rsp);
 454        return rc;
 455}
 456
 457int
 458SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses,
 459                const struct nls_table *nls_cp)
 460{
 461        struct smb2_sess_setup_req *req;
 462        struct smb2_sess_setup_rsp *rsp = NULL;
 463        struct kvec iov[2];
 464        int rc = 0;
 465        int resp_buftype;
 466        __le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is multistage */
 467        struct TCP_Server_Info *server;
 468        unsigned int sec_flags;
 469        u8 temp = 0;
 470        u16 blob_length = 0;
 471        char *security_blob;
 472        char *ntlmssp_blob = NULL;
 473        bool use_spnego = false; /* else use raw ntlmssp */
 474
 475        cFYI(1, "Session Setup");
 476
 477        if (ses->server)
 478                server = ses->server;
 479        else {
 480                rc = -EIO;
 481                return rc;
 482        }
 483
 484        /*
 485         * If memory allocation is successful, caller of this function
 486         * frees it.
 487         */
 488        ses->ntlmssp = kmalloc(sizeof(struct ntlmssp_auth), GFP_KERNEL);
 489        if (!ses->ntlmssp)
 490                return -ENOMEM;
 491
 492        ses->server->secType = RawNTLMSSP;
 493
 494ssetup_ntlmssp_authenticate:
 495        if (phase == NtLmChallenge)
 496                phase = NtLmAuthenticate; /* if ntlmssp, now final phase */
 497
 498        rc = small_smb2_init(SMB2_SESSION_SETUP, NULL, (void **) &req);
 499        if (rc)
 500                return rc;
 501
 502        /* if any of auth flags (ie not sign or seal) are overriden use them */
 503        if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
 504                sec_flags = ses->overrideSecFlg;  /* BB FIXME fix sign flags?*/
 505        else /* if override flags set only sign/seal OR them with global auth */
 506                sec_flags = global_secflags | ses->overrideSecFlg;
 507
 508        cFYI(1, "sec_flags 0x%x", sec_flags);
 509
 510        req->hdr.SessionId = 0; /* First session, not a reauthenticate */
 511        req->VcNumber = 0; /* MBZ */
 512        /* to enable echos and oplocks */
 513        req->hdr.CreditRequest = cpu_to_le16(3);
 514
 515        /* only one of SMB2 signing flags may be set in SMB2 request */
 516        if ((sec_flags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN)
 517                temp = SMB2_NEGOTIATE_SIGNING_REQUIRED;
 518        else if (ses->server->sec_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED)
 519                temp = SMB2_NEGOTIATE_SIGNING_REQUIRED;
 520        else if (sec_flags & CIFSSEC_MAY_SIGN) /* MAY_SIGN is a single flag */
 521                temp = SMB2_NEGOTIATE_SIGNING_ENABLED;
 522
 523        req->SecurityMode = temp;
 524        req->Capabilities = 0;
 525        req->Channel = 0; /* MBZ */
 526
 527        iov[0].iov_base = (char *)req;
 528        /* 4 for rfc1002 length field and 1 for pad */
 529        iov[0].iov_len = get_rfc1002_length(req) + 4 - 1;
 530        if (phase == NtLmNegotiate) {
 531                ntlmssp_blob = kmalloc(sizeof(struct _NEGOTIATE_MESSAGE),
 532                                       GFP_KERNEL);
 533                if (ntlmssp_blob == NULL) {
 534                        rc = -ENOMEM;
 535                        goto ssetup_exit;
 536                }
 537                build_ntlmssp_negotiate_blob(ntlmssp_blob, ses);
 538                if (use_spnego) {
 539                        /* blob_length = build_spnego_ntlmssp_blob(
 540                                        &security_blob,
 541                                        sizeof(struct _NEGOTIATE_MESSAGE),
 542                                        ntlmssp_blob); */
 543                        /* BB eventually need to add this */
 544                        cERROR(1, "spnego not supported for SMB2 yet");
 545                        rc = -EOPNOTSUPP;
 546                        kfree(ntlmssp_blob);
 547                        goto ssetup_exit;
 548                } else {
 549                        blob_length = sizeof(struct _NEGOTIATE_MESSAGE);
 550                        /* with raw NTLMSSP we don't encapsulate in SPNEGO */
 551                        security_blob = ntlmssp_blob;
 552                }
 553        } else if (phase == NtLmAuthenticate) {
 554                req->hdr.SessionId = ses->Suid;
 555                ntlmssp_blob = kzalloc(sizeof(struct _NEGOTIATE_MESSAGE) + 500,
 556                                       GFP_KERNEL);
 557                if (ntlmssp_blob == NULL) {
 558                        cERROR(1, "failed to malloc ntlmssp blob");
 559                        rc = -ENOMEM;
 560                        goto ssetup_exit;
 561                }
 562                rc = build_ntlmssp_auth_blob(ntlmssp_blob, &blob_length, ses,
 563                                             nls_cp);
 564                if (rc) {
 565                        cFYI(1, "build_ntlmssp_auth_blob failed %d", rc);
 566                        goto ssetup_exit; /* BB double check error handling */
 567                }
 568                if (use_spnego) {
 569                        /* blob_length = build_spnego_ntlmssp_blob(
 570                                                        &security_blob,
 571                                                        blob_length,
 572                                                        ntlmssp_blob); */
 573                        cERROR(1, "spnego not supported for SMB2 yet");
 574                        rc = -EOPNOTSUPP;
 575                        kfree(ntlmssp_blob);
 576                        goto ssetup_exit;
 577                } else {
 578                        security_blob = ntlmssp_blob;
 579                }
 580        } else {
 581                cERROR(1, "illegal ntlmssp phase");
 582                rc = -EIO;
 583                goto ssetup_exit;
 584        }
 585
 586        /* Testing shows that buffer offset must be at location of Buffer[0] */
 587        req->SecurityBufferOffset =
 588                                cpu_to_le16(sizeof(struct smb2_sess_setup_req) -
 589                                            1 /* pad */ - 4 /* rfc1001 len */);
 590        req->SecurityBufferLength = cpu_to_le16(blob_length);
 591        iov[1].iov_base = security_blob;
 592        iov[1].iov_len = blob_length;
 593
 594        inc_rfc1001_len(req, blob_length - 1 /* pad */);
 595
 596        /* BB add code to build os and lm fields */
 597
 598        rc = SendReceive2(xid, ses, iov, 2, &resp_buftype, CIFS_LOG_ERROR);
 599
 600        kfree(security_blob);
 601        rsp = (struct smb2_sess_setup_rsp *)iov[0].iov_base;
 602        if (rsp->hdr.Status == STATUS_MORE_PROCESSING_REQUIRED) {
 603                if (phase != NtLmNegotiate) {
 604                        cERROR(1, "Unexpected more processing error");
 605                        goto ssetup_exit;
 606                }
 607                if (offsetof(struct smb2_sess_setup_rsp, Buffer) - 4 !=
 608                        le16_to_cpu(rsp->SecurityBufferOffset)) {
 609                        cERROR(1, "Invalid security buffer offset %d",
 610                                  le16_to_cpu(rsp->SecurityBufferOffset));
 611                        rc = -EIO;
 612                        goto ssetup_exit;
 613                }
 614
 615                /* NTLMSSP Negotiate sent now processing challenge (response) */
 616                phase = NtLmChallenge; /* process ntlmssp challenge */
 617                rc = 0; /* MORE_PROCESSING is not an error here but expected */
 618                ses->Suid = rsp->hdr.SessionId;
 619                rc = decode_ntlmssp_challenge(rsp->Buffer,
 620                                le16_to_cpu(rsp->SecurityBufferLength), ses);
 621        }
 622
 623        /*
 624         * BB eventually add code for SPNEGO decoding of NtlmChallenge blob,
 625         * but at least the raw NTLMSSP case works.
 626         */
 627        /*
 628         * No tcon so can't do
 629         * cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[SMB2...]);
 630         */
 631        if (rc != 0)
 632                goto ssetup_exit;
 633
 634        if (rsp == NULL) {
 635                rc = -EIO;
 636                goto ssetup_exit;
 637        }
 638
 639        ses->session_flags = le16_to_cpu(rsp->SessionFlags);
 640ssetup_exit:
 641        free_rsp_buf(resp_buftype, rsp);
 642
 643        /* if ntlmssp, and negotiate succeeded, proceed to authenticate phase */
 644        if ((phase == NtLmChallenge) && (rc == 0))
 645                goto ssetup_ntlmssp_authenticate;
 646        return rc;
 647}
 648
 649int
 650SMB2_logoff(const unsigned int xid, struct cifs_ses *ses)
 651{
 652        struct smb2_logoff_req *req; /* response is also trivial struct */
 653        int rc = 0;
 654        struct TCP_Server_Info *server;
 655
 656        cFYI(1, "disconnect session %p", ses);
 657
 658        if (ses && (ses->server))
 659                server = ses->server;
 660        else
 661                return -EIO;
 662
 663        rc = small_smb2_init(SMB2_LOGOFF, NULL, (void **) &req);
 664        if (rc)
 665                return rc;
 666
 667         /* since no tcon, smb2_init can not do this, so do here */
 668        req->hdr.SessionId = ses->Suid;
 669
 670        rc = SendReceiveNoRsp(xid, ses, (char *) &req->hdr, 0);
 671        /*
 672         * No tcon so can't do
 673         * cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[SMB2...]);
 674         */
 675        return rc;
 676}
 677
 678static inline void cifs_stats_fail_inc(struct cifs_tcon *tcon, uint16_t code)
 679{
 680        cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_failed[code]);
 681}
 682
 683#define MAX_SHARENAME_LENGTH (255 /* server */ + 80 /* share */ + 1 /* NULL */)
 684
 685int
 686SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
 687          struct cifs_tcon *tcon, const struct nls_table *cp)
 688{
 689        struct smb2_tree_connect_req *req;
 690        struct smb2_tree_connect_rsp *rsp = NULL;
 691        struct kvec iov[2];
 692        int rc = 0;
 693        int resp_buftype;
 694        int unc_path_len;
 695        struct TCP_Server_Info *server;
 696        __le16 *unc_path = NULL;
 697
 698        cFYI(1, "TCON");
 699
 700        if ((ses->server) && tree)
 701                server = ses->server;
 702        else
 703                return -EIO;
 704
 705        if (tcon && tcon->bad_network_name)
 706                return -ENOENT;
 707
 708        unc_path = kmalloc(MAX_SHARENAME_LENGTH * 2, GFP_KERNEL);
 709        if (unc_path == NULL)
 710                return -ENOMEM;
 711
 712        unc_path_len = cifs_strtoUTF16(unc_path, tree, strlen(tree), cp) + 1;
 713        unc_path_len *= 2;
 714        if (unc_path_len < 2) {
 715                kfree(unc_path);
 716                return -EINVAL;
 717        }
 718
 719        rc = small_smb2_init(SMB2_TREE_CONNECT, tcon, (void **) &req);
 720        if (rc) {
 721                kfree(unc_path);
 722                return rc;
 723        }
 724
 725        if (tcon == NULL) {
 726                /* since no tcon, smb2_init can not do this, so do here */
 727                req->hdr.SessionId = ses->Suid;
 728                /* if (ses->server->sec_mode & SECMODE_SIGN_REQUIRED)
 729                        req->hdr.Flags |= SMB2_FLAGS_SIGNED; */
 730        }
 731
 732        iov[0].iov_base = (char *)req;
 733        /* 4 for rfc1002 length field and 1 for pad */
 734        iov[0].iov_len = get_rfc1002_length(req) + 4 - 1;
 735
 736        /* Testing shows that buffer offset must be at location of Buffer[0] */
 737        req->PathOffset = cpu_to_le16(sizeof(struct smb2_tree_connect_req)
 738                        - 1 /* pad */ - 4 /* do not count rfc1001 len field */);
 739        req->PathLength = cpu_to_le16(unc_path_len - 2);
 740        iov[1].iov_base = unc_path;
 741        iov[1].iov_len = unc_path_len;
 742
 743        inc_rfc1001_len(req, unc_path_len - 1 /* pad */);
 744
 745        rc = SendReceive2(xid, ses, iov, 2, &resp_buftype, 0);
 746        rsp = (struct smb2_tree_connect_rsp *)iov[0].iov_base;
 747
 748        if (rc != 0) {
 749                if (tcon) {
 750                        cifs_stats_fail_inc(tcon, SMB2_TREE_CONNECT_HE);
 751                        tcon->need_reconnect = true;
 752                }
 753                goto tcon_error_exit;
 754        }
 755
 756        if (rsp == NULL) {
 757                rc = -EIO;
 758                goto tcon_exit;
 759        }
 760
 761        if (tcon == NULL) {
 762                ses->ipc_tid = rsp->hdr.TreeId;
 763                goto tcon_exit;
 764        }
 765
 766        if (rsp->ShareType & SMB2_SHARE_TYPE_DISK)
 767                cFYI(1, "connection to disk share");
 768        else if (rsp->ShareType & SMB2_SHARE_TYPE_PIPE) {
 769                tcon->ipc = true;
 770                cFYI(1, "connection to pipe share");
 771        } else if (rsp->ShareType & SMB2_SHARE_TYPE_PRINT) {
 772                tcon->print = true;
 773                cFYI(1, "connection to printer");
 774        } else {
 775                cERROR(1, "unknown share type %d", rsp->ShareType);
 776                rc = -EOPNOTSUPP;
 777                goto tcon_error_exit;
 778        }
 779
 780        tcon->share_flags = le32_to_cpu(rsp->ShareFlags);
 781        tcon->maximal_access = le32_to_cpu(rsp->MaximalAccess);
 782        tcon->tidStatus = CifsGood;
 783        tcon->need_reconnect = false;
 784        tcon->tid = rsp->hdr.TreeId;
 785        strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
 786
 787        if ((rsp->Capabilities & SMB2_SHARE_CAP_DFS) &&
 788            ((tcon->share_flags & SHI1005_FLAGS_DFS) == 0))
 789                cERROR(1, "DFS capability contradicts DFS flag");
 790
 791tcon_exit:
 792        free_rsp_buf(resp_buftype, rsp);
 793        kfree(unc_path);
 794        return rc;
 795
 796tcon_error_exit:
 797        if (rsp->hdr.Status == STATUS_BAD_NETWORK_NAME) {
 798                cERROR(1, "BAD_NETWORK_NAME: %s", tree);
 799                tcon->bad_network_name = true;
 800        }
 801        goto tcon_exit;
 802}
 803
 804int
 805SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon)
 806{
 807        struct smb2_tree_disconnect_req *req; /* response is trivial */
 808        int rc = 0;
 809        struct TCP_Server_Info *server;
 810        struct cifs_ses *ses = tcon->ses;
 811
 812        cFYI(1, "Tree Disconnect");
 813
 814        if (ses && (ses->server))
 815                server = ses->server;
 816        else
 817                return -EIO;
 818
 819        if ((tcon->need_reconnect) || (tcon->ses->need_reconnect))
 820                return 0;
 821
 822        rc = small_smb2_init(SMB2_TREE_DISCONNECT, tcon, (void **) &req);
 823        if (rc)
 824                return rc;
 825
 826        rc = SendReceiveNoRsp(xid, ses, (char *)&req->hdr, 0);
 827        if (rc)
 828                cifs_stats_fail_inc(tcon, SMB2_TREE_DISCONNECT_HE);
 829
 830        return rc;
 831}
 832
 833int
 834SMB2_open(const unsigned int xid, struct cifs_tcon *tcon, __le16 *path,
 835          u64 *persistent_fid, u64 *volatile_fid, __u32 desired_access,
 836          __u32 create_disposition, __u32 file_attributes, __u32 create_options)
 837{
 838        struct smb2_create_req *req;
 839        struct smb2_create_rsp *rsp;
 840        struct TCP_Server_Info *server;
 841        struct cifs_ses *ses = tcon->ses;
 842        struct kvec iov[2];
 843        int resp_buftype;
 844        int uni_path_len;
 845        int rc = 0;
 846        int num_iovecs = 2;
 847
 848        cFYI(1, "create/open");
 849
 850        if (ses && (ses->server))
 851                server = ses->server;
 852        else
 853                return -EIO;
 854
 855        rc = small_smb2_init(SMB2_CREATE, tcon, (void **) &req);
 856        if (rc)
 857                return rc;
 858
 859        if (enable_oplocks)
 860                req->RequestedOplockLevel = SMB2_OPLOCK_LEVEL_BATCH;
 861        else
 862                req->RequestedOplockLevel = SMB2_OPLOCK_LEVEL_NONE;
 863        req->ImpersonationLevel = IL_IMPERSONATION;
 864        req->DesiredAccess = cpu_to_le32(desired_access);
 865        /* File attributes ignored on open (used in create though) */
 866        req->FileAttributes = cpu_to_le32(file_attributes);
 867        req->ShareAccess = FILE_SHARE_ALL_LE;
 868        req->CreateDisposition = cpu_to_le32(create_disposition);
 869        req->CreateOptions = cpu_to_le32(create_options);
 870        uni_path_len = (2 * UniStrnlen((wchar_t *)path, PATH_MAX)) + 2;
 871        req->NameOffset = cpu_to_le16(sizeof(struct smb2_create_req)
 872                        - 1 /* pad */ - 4 /* do not count rfc1001 len field */);
 873
 874        iov[0].iov_base = (char *)req;
 875        /* 4 for rfc1002 length field */
 876        iov[0].iov_len = get_rfc1002_length(req) + 4;
 877
 878        /* MUST set path len (NameLength) to 0 opening root of share */
 879        if (uni_path_len >= 4) {
 880                req->NameLength = cpu_to_le16(uni_path_len - 2);
 881                /* -1 since last byte is buf[0] which is sent below (path) */
 882                iov[0].iov_len--;
 883                iov[1].iov_len = uni_path_len;
 884                iov[1].iov_base = path;
 885                /*
 886                 * -1 since last byte is buf[0] which was counted in
 887                 * smb2_buf_len.
 888                 */
 889                inc_rfc1001_len(req, uni_path_len - 1);
 890        } else {
 891                num_iovecs = 1;
 892                req->NameLength = 0;
 893        }
 894
 895        rc = SendReceive2(xid, ses, iov, num_iovecs, &resp_buftype, 0);
 896        rsp = (struct smb2_create_rsp *)iov[0].iov_base;
 897
 898        if (rc != 0) {
 899                cifs_stats_fail_inc(tcon, SMB2_CREATE_HE);
 900                goto creat_exit;
 901        }
 902
 903        if (rsp == NULL) {
 904                rc = -EIO;
 905                goto creat_exit;
 906        }
 907        *persistent_fid = rsp->PersistentFileId;
 908        *volatile_fid = rsp->VolatileFileId;
 909creat_exit:
 910        free_rsp_buf(resp_buftype, rsp);
 911        return rc;
 912}
 913
 914int
 915SMB2_close(const unsigned int xid, struct cifs_tcon *tcon,
 916           u64 persistent_fid, u64 volatile_fid)
 917{
 918        struct smb2_close_req *req;
 919        struct smb2_close_rsp *rsp;
 920        struct TCP_Server_Info *server;
 921        struct cifs_ses *ses = tcon->ses;
 922        struct kvec iov[1];
 923        int resp_buftype;
 924        int rc = 0;
 925
 926        cFYI(1, "Close");
 927
 928        if (ses && (ses->server))
 929                server = ses->server;
 930        else
 931                return -EIO;
 932
 933        rc = small_smb2_init(SMB2_CLOSE, tcon, (void **) &req);
 934        if (rc)
 935                return rc;
 936
 937        req->PersistentFileId = persistent_fid;
 938        req->VolatileFileId = volatile_fid;
 939
 940        iov[0].iov_base = (char *)req;
 941        /* 4 for rfc1002 length field */
 942        iov[0].iov_len = get_rfc1002_length(req) + 4;
 943
 944        rc = SendReceive2(xid, ses, iov, 1, &resp_buftype, 0);
 945        rsp = (struct smb2_close_rsp *)iov[0].iov_base;
 946
 947        if (rc != 0) {
 948                if (tcon)
 949                        cifs_stats_fail_inc(tcon, SMB2_CLOSE_HE);
 950                goto close_exit;
 951        }
 952
 953        if (rsp == NULL) {
 954                rc = -EIO;
 955                goto close_exit;
 956        }
 957
 958        /* BB FIXME - decode close response, update inode for caching */
 959
 960close_exit:
 961        free_rsp_buf(resp_buftype, rsp);
 962        return rc;
 963}
 964
 965static int
 966validate_buf(unsigned int offset, unsigned int buffer_length,
 967             struct smb2_hdr *hdr, unsigned int min_buf_size)
 968
 969{
 970        unsigned int smb_len = be32_to_cpu(hdr->smb2_buf_length);
 971        char *end_of_smb = smb_len + 4 /* RFC1001 length field */ + (char *)hdr;
 972        char *begin_of_buf = 4 /* RFC1001 len field */ + offset + (char *)hdr;
 973        char *end_of_buf = begin_of_buf + buffer_length;
 974
 975
 976        if (buffer_length < min_buf_size) {
 977                cERROR(1, "buffer length %d smaller than minimum size %d",
 978                           buffer_length, min_buf_size);
 979                return -EINVAL;
 980        }
 981
 982        /* check if beyond RFC1001 maximum length */
 983        if ((smb_len > 0x7FFFFF) || (buffer_length > 0x7FFFFF)) {
 984                cERROR(1, "buffer length %d or smb length %d too large",
 985                           buffer_length, smb_len);
 986                return -EINVAL;
 987        }
 988
 989        if ((begin_of_buf > end_of_smb) || (end_of_buf > end_of_smb)) {
 990                cERROR(1, "illegal server response, bad offset to data");
 991                return -EINVAL;
 992        }
 993
 994        return 0;
 995}
 996
 997/*
 998 * If SMB buffer fields are valid, copy into temporary buffer to hold result.
 999 * Caller must free buffer.
1000 */
1001static int
1002validate_and_copy_buf(unsigned int offset, unsigned int buffer_length,
1003                      struct smb2_hdr *hdr, unsigned int minbufsize,
1004                      char *data)
1005
1006{
1007        char *begin_of_buf = 4 /* RFC1001 len field */ + offset + (char *)hdr;
1008        int rc;
1009
1010        if (!data)
1011                return -EINVAL;
1012
1013        rc = validate_buf(offset, buffer_length, hdr, minbufsize);
1014        if (rc)
1015                return rc;
1016
1017        memcpy(data, begin_of_buf, buffer_length);
1018
1019        return 0;
1020}
1021
1022int
1023SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon,
1024                u64 persistent_fid, u64 volatile_fid,
1025                struct smb2_file_all_info *data)
1026{
1027        struct smb2_query_info_req *req;
1028        struct smb2_query_info_rsp *rsp = NULL;
1029        struct kvec iov[2];
1030        int rc = 0;
1031        int resp_buftype;
1032        struct TCP_Server_Info *server;
1033        struct cifs_ses *ses = tcon->ses;
1034
1035        cFYI(1, "Query Info");
1036
1037        if (ses && (ses->server))
1038                server = ses->server;
1039        else
1040                return -EIO;
1041
1042        rc = small_smb2_init(SMB2_QUERY_INFO, tcon, (void **) &req);
1043        if (rc)
1044                return rc;
1045
1046        req->InfoType = SMB2_O_INFO_FILE;
1047        req->FileInfoClass = FILE_ALL_INFORMATION;
1048        req->PersistentFileId = persistent_fid;
1049        req->VolatileFileId = volatile_fid;
1050        /* 4 for rfc1002 length field and 1 for Buffer */
1051        req->InputBufferOffset =
1052                cpu_to_le16(sizeof(struct smb2_query_info_req) - 1 - 4);
1053        req->OutputBufferLength =
1054                cpu_to_le32(sizeof(struct smb2_file_all_info) + MAX_NAME * 2);
1055
1056        iov[0].iov_base = (char *)req;
1057        /* 4 for rfc1002 length field */
1058        iov[0].iov_len = get_rfc1002_length(req) + 4;
1059
1060        rc = SendReceive2(xid, ses, iov, 1, &resp_buftype, 0);
1061        if (rc) {
1062                cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE);
1063                goto qinf_exit;
1064        }
1065
1066        rsp = (struct smb2_query_info_rsp *)iov[0].iov_base;
1067
1068        rc = validate_and_copy_buf(le16_to_cpu(rsp->OutputBufferOffset),
1069                                   le32_to_cpu(rsp->OutputBufferLength),
1070                                   &rsp->hdr, sizeof(struct smb2_file_all_info),
1071                                   (char *)data);
1072
1073qinf_exit:
1074        free_rsp_buf(resp_buftype, rsp);
1075        return rc;
1076}
1077
1078/*
1079 * This is a no-op for now. We're not really interested in the reply, but
1080 * rather in the fact that the server sent one and that server->lstrp
1081 * gets updated.
1082 *
1083 * FIXME: maybe we should consider checking that the reply matches request?
1084 */
1085static void
1086smb2_echo_callback(struct mid_q_entry *mid)
1087{
1088        struct TCP_Server_Info *server = mid->callback_data;
1089        struct smb2_echo_rsp *smb2 = (struct smb2_echo_rsp *)mid->resp_buf;
1090        unsigned int credits_received = 1;
1091
1092        if (mid->mid_state == MID_RESPONSE_RECEIVED)
1093                credits_received = le16_to_cpu(smb2->hdr.CreditRequest);
1094
1095        DeleteMidQEntry(mid);
1096        add_credits(server, credits_received, CIFS_ECHO_OP);
1097}
1098
1099int
1100SMB2_echo(struct TCP_Server_Info *server)
1101{
1102        struct smb2_echo_req *req;
1103        int rc = 0;
1104        struct kvec iov;
1105
1106        cFYI(1, "In echo request");
1107
1108        rc = small_smb2_init(SMB2_ECHO, NULL, (void **)&req);
1109        if (rc)
1110                return rc;
1111
1112        req->hdr.CreditRequest = cpu_to_le16(1);
1113
1114        iov.iov_base = (char *)req;
1115        /* 4 for rfc1002 length field */
1116        iov.iov_len = get_rfc1002_length(req) + 4;
1117
1118        rc = cifs_call_async(server, &iov, 1, NULL, smb2_echo_callback, server,
1119                             CIFS_ECHO_OP);
1120        if (rc)
1121                cFYI(1, "Echo request failed: %d", rc);
1122
1123        cifs_small_buf_release(req);
1124        return rc;
1125}
1126
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.