1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2016 Nexenta Systems, Inc. All rights reserved.
  24  */
  25 
  26 #include <smbsrv/smb_kproto.h>
  27 #include <smbsrv/smb_share.h>
  28 
  29 static void
  30 smb_tcon_puterror(smb_request_t *sr, uint32_t status)
  31 {
  32 
  33         switch (status) {
  34 
  35         case NT_STATUS_BAD_NETWORK_NAME:
  36                 /* Intentional status=0 */
  37                 smbsr_error(sr, 0, ERRSRV, ERRinvnetname);
  38                 break;
  39 
  40         case NT_STATUS_ACCESS_DENIED:
  41                 smbsr_error(sr, status, ERRSRV, ERRaccess);
  42                 break;
  43 
  44         case NT_STATUS_BAD_DEVICE_TYPE:
  45                 smbsr_error(sr, status, ERRDOS, ERROR_BAD_DEV_TYPE);
  46                 break;
  47 
  48         default:
  49         case NT_STATUS_INTERNAL_ERROR:
  50                 /* Intentional status=0 */
  51                 smbsr_error(sr, 0, ERRSRV, ERRsrverror);
  52                 break;
  53         }
  54 }
  55 
  56 /*
  57  * SmbTreeConnect: Map a share to a tree and obtain a tree-id (TID).
  58  *
  59  * Client Request                     Description
  60  * ================================== =================================
  61  *
  62  * UCHAR WordCount;                   Count of parameter words = 0
  63  * USHORT ByteCount;                  Count of data bytes;    min = 4
  64  * UCHAR BufferFormat1;               0x04
  65  * STRING Path[];                     Server name and share name
  66  * UCHAR BufferFormat2;               0x04
  67  * STRING Password[];                 Password
  68  * UCHAR BufferFormat3;               0x04
  69  * STRING Service[];                  Service name
  70  *
  71  * The CIFS server responds with:
  72  *
  73  * Server Response                  Description
  74  * ================================ =================================
  75  *
  76  * UCHAR WordCount;                 Count of parameter words = 2
  77  * USHORT MaxBufferSize;            Max size message the server handles
  78  * USHORT Tid;                      Tree ID
  79  * USHORT ByteCount;                Count of data bytes = 0
  80  *
  81  * If the negotiated dialect is MICROSOFT NETWORKS 1.03 or earlier,
  82  * MaxBufferSize in the response message indicates the maximum size
  83  * message that the server can handle.  The client should not generate
  84  * messages, nor expect to receive responses, larger than this.  This
  85  * must be constant for a given server. For newer dialects, this field
  86  * is ignored.
  87  */
  88 smb_sdrc_t
  89 smb_pre_tree_connect(smb_request_t *sr)
  90 {
  91         smb_arg_tcon_t  *tcon = &sr->sr_tcon;
  92         int             rc;
  93 
  94         /*
  95          * Perhaps this should be "%A.sA" now that unicode is enabled.
  96          */
  97         rc = smbsr_decode_data(sr, "%AAA", sr, &tcon->path,
  98             &tcon->password, &tcon->service);
  99 
 100         tcon->flags = 0;
 101         tcon->optional_support = 0;
 102 
 103         DTRACE_SMB_2(op__TreeConnect__start, smb_request_t *, sr,
 104             smb_arg_tcon_t *, tcon);
 105 
 106         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 107 }
 108 
 109 void
 110 smb_post_tree_connect(smb_request_t *sr)
 111 {
 112         DTRACE_SMB_1(op__TreeConnect__done, smb_request_t *, sr);
 113 }
 114 
 115 smb_sdrc_t
 116 smb_com_tree_connect(smb_request_t *sr)
 117 {
 118         uint32_t status;
 119         int rc;
 120 
 121         status = smb_tree_connect(sr);
 122         if (status) {
 123                 smb_tcon_puterror(sr, status);
 124                 return (SDRC_ERROR);
 125         }
 126 
 127         rc = smbsr_encode_result(sr, 2, 0, "bwww",
 128             2,                          /* wct */
 129             (WORD)smb_maxbufsize,       /* MaxBufferSize */
 130             sr->smb_tid,             /* TID */
 131             0);                         /* bcc */
 132 
 133         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 134 }
 135 
 136 /*
 137  * SmbTreeConnectX: Map a share to a tree and obtain a tree-id (TID).
 138  *
 139  * Client Request                     Description
 140  * =================================  =================================
 141  *
 142  * UCHAR WordCount;                   Count of parameter words = 4
 143  * UCHAR AndXCommand;                 Secondary (X) command; 0xFF = none
 144  * UCHAR AndXReserved;                Reserved (must be 0)
 145  * USHORT AndXOffset;                 Offset to next command WordCount
 146  * USHORT Flags;                      Additional information
 147  *                                    bit 0 set = disconnect Tid
 148  * USHORT PasswordLength;             Length of Password[]
 149  * USHORT ByteCount;                  Count of data bytes;    min = 3
 150  * UCHAR Password[];                  Password
 151  * STRING Path[];                     Server name and share name
 152  * STRING Service[];                  Service name
 153  *
 154  * If the negotiated dialect is LANMAN1.0 or later, then it is a protocol
 155  * violation for the client to send this message prior to a successful
 156  * SMB_COM_SESSION_SETUP_ANDX, and the server ignores Password.
 157  *
 158  * If the negotiated dialect is prior to LANMAN1.0 and the client has not
 159  * sent a successful SMB_COM_SESSION_SETUP_ANDX request when the tree
 160  * connect arrives, a user level security mode server must nevertheless
 161  * validate the client's credentials.
 162  *
 163  * Flags (prefix with TREE_CONNECT_ANDX_):
 164  * ==========================  ========================================
 165  * 0x0001 DISCONECT_TID        The tree specified by TID in the SMB header
 166  *                             should be disconnected - disconnect errors
 167  *                             should be ignored.
 168  *
 169  * 0x0004 EXTENDED_SIGNATURES  Client request for signing key protection.
 170  *
 171  * 0x0008 EXTENDED_RESPONSE    Client request for extended information.
 172  *
 173  * Path follows UNC style syntax (\\server\share) and indicates the name
 174  * of the resource to which the client wishes to connect.
 175  *
 176  * Because Password may be an authentication response, it is a variable
 177  * length field with the length specified by PasswordLength.   If
 178  * authentication is not being used, Password should be a null terminated
 179  * ASCII string with PasswordLength set to the string size including the
 180  * terminating null.
 181  *
 182  * The server can enforce whatever policy it desires to govern share
 183  * access.  Administrative privilege is required for administrative
 184  * shares (C$, etc.).
 185  *
 186  * The Service component indicates the type of resource the client
 187  * intends to access.  Valid values are:
 188  *
 189  * Service   Description               Earliest Dialect Allowed
 190  * ========  ========================  ================================
 191  *
 192  * A:        disk share                PC NETWORK PROGRAM 1.0
 193  * LPT1:     printer                   PC NETWORK PROGRAM 1.0
 194  * IPC       named pipe                MICROSOFT NETWORKS 3.0
 195  * COMM      communications device     MICROSOFT NETWORKS 3.0
 196  * ?????     any type of device        MICROSOFT NETWORKS 3.0
 197  *
 198  * If the negotiated dialect is earlier than DOS LANMAN2.1, the response to
 199  * this SMB is:
 200  *
 201  * Server Response                  Description
 202  * ================================ ===================================
 203  *
 204  * UCHAR WordCount;                 Count of parameter words = 2
 205  * UCHAR AndXCommand;               Secondary (X) command;  0xFF = none
 206  * UCHAR AndXReserved;              Reserved (must be 0)
 207  * USHORT AndXOffset;               Offset to next command WordCount
 208  * USHORT ByteCount;                Count of data bytes;    min = 3
 209  *
 210  * If the negotiated is DOS LANMAN2.1 or later, the response to this SMB
 211  * is:
 212  *
 213  * Server Response                  Description
 214  * ================================ ===================================
 215  *
 216  * UCHAR WordCount;                 Count of parameter words = 3
 217  * UCHAR AndXCommand;               Secondary (X) command;  0xFF = none
 218  * UCHAR AndXReserved;              Reserved (must be 0)
 219  * USHORT AndXOffset;               Offset to next command WordCount
 220  * USHORT OptionalSupport;          Optional support bits
 221  * USHORT ByteCount;                Count of data bytes;    min = 3
 222  * UCHAR Service[];                 Service type connected to.  Always
 223  *                                   ANSII.
 224  * STRING NativeFileSystem[];       Native file system for this tree
 225  *
 226  * NativeFileSystem is the name of the filesystem; values to be expected
 227  * include FAT, NTFS, etc.
 228  *
 229  * OptionalSupport:
 230  * ==============================  ==========================
 231  * 0x0001 SMB_SUPPORT_SEARCH_BITS  The server supports the use of Search
 232  *                                 Attributes in client requests.
 233  * 0x0002 SMB_SHARE_IS_IN_DFS      The share is managed by DFS.
 234  * 0x000C SMB_CSC_MASK             Offline-caching mask - see CSC flags.
 235  * 0x0010 SMB_UNIQUE_FILE_NAME     The server uses long names and does not
 236  *                                 support short names.  Indicator for
 237  *                                 clients directory/name-space caching.
 238  * 0x0020 SMB_EXTENDED_SIGNATURES  The server will use signing key protection.
 239  *
 240  * Client-side caching (offline files):
 241  * ==============================  ==========================
 242  * 0x0000 SMB_CSC_CACHE_MANUAL_REINT Clients may cache files for offline use
 243  *                                 but automatic file-by-file reintegration
 244  *                                 is not allowed.
 245  * 0x0004 SMB_CSC_CACHE_AUTO_REINT Automatic file-by-file reintegration is
 246  *                                 allowed.
 247  * 0x0008 SMB_CSC_CACHE_VDO        File opens do not need to be flowed.
 248  * 0x000C SMB_CSC_CACHE_NONE       CSC is disabled for this share.
 249  *
 250  * Some servers negotiate "DOS LANMAN2.1" dialect or later and still send
 251  * the "downlevel" (i.e. wordcount==2) response.  Valid AndX following
 252  * commands are
 253  *
 254  * SMB_COM_OPEN              SMB_COM_OPEN_ANDX          SMB_COM_CREATE
 255  * SMB_COM_CREATE_NEW        SMB_COM_CREATE_DIRECTORY   SMB_COM_DELETE
 256  * SMB_COM_DELETE_DIRECTORY  SMB_COM_FIND               SMB_COM_COPY
 257  * SMB_COM_FIND_UNIQUE       SMB_COM_RENAME
 258  * SMB_COM_CHECK_DIRECTORY   SMB_COM_QUERY_INFORMATION
 259  * SMB_COM_GET_PRINT_QUEUE   SMB_COM_OPEN_PRINT_FILE
 260  * SMB_COM_TRANSACTION       SMB_COM_NO_ANDX_CMD
 261  * SMB_COM_SET_INFORMATION   SMB_COM_NT_RENAME
 262  *
 263  * Errors:
 264  * ERRDOS/ERRnomem
 265  * ERRDOS/ERRbadpath
 266  * ERRDOS/ERRinvdevice
 267  * ERRSRV/ERRaccess
 268  * ERRSRV/ERRbadpw
 269  * ERRSRV/ERRinvnetname
 270  */
 271 smb_sdrc_t
 272 smb_pre_tree_connect_andx(smb_request_t *sr)
 273 {
 274         smb_arg_tcon_t  *tcon = &sr->sr_tcon;
 275         uint8_t         *pwbuf = NULL;
 276         uint16_t        pwlen = 0;
 277         int             rc;
 278 
 279         rc = smbsr_decode_vwv(sr, "b.www", &sr->andx_com, &sr->andx_off,
 280             &tcon->flags, &pwlen);
 281         if (rc == 0) {
 282                 if (pwlen != 0)
 283                         pwbuf = smb_srm_zalloc(sr, pwlen);
 284 
 285                 rc = smbsr_decode_data(sr, "%#cus", sr, pwlen, pwbuf,
 286                     &tcon->path, &tcon->service);
 287 
 288                 tcon->pwdlen = pwlen;
 289                 tcon->password = (char *)pwbuf;
 290         }
 291 
 292         tcon->optional_support = 0;
 293 
 294         DTRACE_SMB_2(op__TreeConnectX__start, smb_request_t *, sr,
 295             smb_arg_tcon_t *, tcon);
 296 
 297         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 298 }
 299 
 300 void
 301 smb_post_tree_connect_andx(smb_request_t *sr)
 302 {
 303         DTRACE_SMB_1(op__TreeConnectX__done, smb_request_t *, sr);
 304 }
 305 
 306 smb_sdrc_t
 307 smb_com_tree_connect_andx(smb_request_t *sr)
 308 {
 309         smb_arg_tcon_t  *tcon = &sr->sr_tcon;
 310         smb_tree_t      *tree;
 311         char            *service;
 312         uint32_t        status;
 313         int             rc;
 314 
 315         if (tcon->flags & SMB_TCONX_DISCONECT_TID) {
 316                 tree = smb_session_lookup_tree(sr->session, sr->smb_tid);
 317                 if (tree != NULL) {
 318                         smb_tree_disconnect(tree, B_TRUE);
 319                         smb_session_cancel_requests(sr->session, tree, sr);
 320                 }
 321         }
 322 
 323         status = smb_tree_connect(sr);
 324         if (status) {
 325                 smb_tcon_puterror(sr, status);
 326                 return (SDRC_ERROR);
 327         }
 328         tree = sr->tid_tree;
 329 
 330         switch (tree->t_res_type & STYPE_MASK) {
 331         case STYPE_IPC:
 332                 service = "IPC";
 333                 break;
 334         case STYPE_PRINTQ:
 335                 service = "LPT1:";
 336                 break;
 337         case STYPE_DISKTREE:
 338         default:
 339                 service = "A:";
 340         }
 341 
 342         if (sr->session->dialect < NT_LM_0_12) {
 343                 rc = smbsr_encode_result(sr, 2, VAR_BCC, "bb.wwss",
 344                     (char)2,            /* wct */
 345                     sr->andx_com,
 346                     VAR_BCC,
 347                     VAR_BCC,
 348                     service,
 349                     tree->t_typename);
 350         } else if ((tcon->flags & SMB_TCONX_EXTENDED_RESPONSE) == 0) {
 351                 rc = smbsr_encode_result(sr, 3, VAR_BCC, "bb.wwws%u",
 352                     (char)3,            /* wct */
 353                     sr->andx_com,
 354                     (short)64,
 355                     tcon->optional_support,
 356                     VAR_BCC,
 357                     service,
 358                     sr,
 359                     tree->t_typename);
 360 
 361         } else {
 362                 rc = smbsr_encode_result(sr, 7, VAR_BCC, "bb.wwllws%u",
 363                     (char)7,            /* wct (b) */
 364                     sr->andx_com,    /* AndXcmd (b) */
 365                     (short)72,          /* AndXoff (w) */
 366                     tcon->optional_support,  /* (w) */
 367                     tree->t_access,          /* (l) */
 368                     0,          /*    guest_access (l) */
 369                     VAR_BCC,            /* (w) */
 370                     service,            /* (s) */
 371                     sr,                 /* (%) */
 372                     tree->t_typename);       /* (u) */
 373         }
 374 
 375         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 376 }
 377 
 378 /*
 379  * SmbTreeDisconnect: Disconnect a tree.
 380  *
 381  * Note: SDDF_SUPPRESS_UID is set for this operation, which means the sr
 382  * uid_user field will not be valid on entry to these functions.  Do not
 383  * use it until it is set up in smb_com_tree_disconnect() or the system
 384  * will panic.
 385  *
 386  * Note: there are scenarios in which the client does not send a tree
 387  * disconnect request, for example, when ERRbaduid is returned from
 388  * SmbReadX after a user has logged off.  Any open files will remain
 389  * around until the session is destroyed.
 390  *
 391  * Client Request                     Description
 392  * ================================== =================================
 393  *
 394  * UCHAR WordCount;                   Count of parameter words = 0
 395  * USHORT ByteCount;                  Count of data bytes = 0
 396  *
 397  * The resource sharing connection identified by Tid in the SMB header is
 398  * logically disconnected from the server. Tid is invalidated; it will not
 399  * be recognized if used by the client for subsequent requests. All locks,
 400  * open files, etc. created on behalf of Tid are released.
 401  *
 402  * Server Response                    Description
 403  * ================================== =================================
 404  *
 405  * UCHAR WordCount;                   Count of parameter words = 0
 406  * USHORT ByteCount;                  Count of data bytes = 0
 407  *
 408  * Errors:
 409  * ERRSRV/ERRinvnid
 410  * ERRSRV/ERRbaduid
 411  */
 412 smb_sdrc_t
 413 smb_pre_tree_disconnect(smb_request_t *sr)
 414 {
 415         sr->uid_user = smb_session_lookup_uid(sr->session, sr->smb_uid);
 416         sr->tid_tree = smb_session_lookup_tree(sr->session, sr->smb_tid);
 417 
 418         DTRACE_SMB_1(op__TreeDisconnect__start, smb_request_t *, sr);
 419         return (SDRC_SUCCESS);
 420 }
 421 
 422 void
 423 smb_post_tree_disconnect(smb_request_t *sr)
 424 {
 425         DTRACE_SMB_1(op__TreeDisconnect__done, smb_request_t *, sr);
 426 }
 427 
 428 /*
 429  * SmbTreeDisconnect requires a valid UID as well as a valid TID.  Some
 430  * clients logoff a user and then try to disconnect the trees connected
 431  * by the user who has just been logged off, which would normally fail
 432  * in the dispatch code with ERRbaduid but, unfortunately, ERRbaduid
 433  * causes a problem for some of those clients.  Windows returns ERRinvnid.
 434  *
 435  * To prevent ERRbaduid being returned, the UID and TID are looked up here
 436  * rather than prior to dispatching SmbTreeDisconnect requests.  If either
 437  * the UID or the TID is invalid, ERRinvnid is returned.
 438  */
 439 smb_sdrc_t
 440 smb_com_tree_disconnect(smb_request_t *sr)
 441 {
 442         if (sr->uid_user == NULL || sr->tid_tree == NULL) {
 443                 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRinvnid);
 444                 return (SDRC_ERROR);
 445         }
 446 
 447         sr->user_cr = smb_user_getcred(sr->uid_user);
 448 
 449         smb_tree_disconnect(sr->tid_tree, B_TRUE);
 450         smb_session_cancel_requests(sr->session, sr->tid_tree, sr);
 451 
 452         if (smbsr_encode_empty_result(sr))
 453                 return (SDRC_ERROR);
 454 
 455         return (SDRC_SUCCESS);
 456 }