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 2010 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  *
  25  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  26  */
  27 
  28 #include <smbsrv/smb_kproto.h>
  29 #include <smbsrv/smbinfo.h>
  30 #include <smbsrv/smb_fsops.h>
  31 
  32 /*
  33  * The create directory message is sent to create a new directory.  The
  34  * appropriate Tid and additional pathname are passed.  The directory must
  35  * not exist for it to be created.
  36  *
  37  * Client Request                     Description
  38  * ================================== =================================
  39  * UCHAR WordCount;                   Count of parameter words = 0
  40  * USHORT ByteCount;                  Count of data bytes; min = 2
  41  * UCHAR BufferFormat;                0x04
  42  * STRING DirectoryName[];            Directory name
  43  *
  44  * Servers require clients to have at least create permission for the
  45  * subtree containing the directory in order to create a new directory.
  46  * The creator's access rights to the new directory are be determined by
  47  * local policy on the server.
  48  *
  49  * Server Response                    Description
  50  * ================================== =================================
  51  * UCHAR WordCount;                   Count of parameter words = 0
  52  * USHORT ByteCount;                  Count of data bytes = 0
  53  */
  54 smb_sdrc_t
  55 smb_pre_create_directory(smb_request_t *sr)
  56 {
  57         int rc;
  58 
  59         rc = smbsr_decode_data(sr, "%S", sr,
  60             &sr->arg.dirop.fqi.fq_path.pn_path);
  61 
  62         DTRACE_SMB_2(op__CreateDirectory__start, smb_request_t *, sr,
  63             struct dirop *, &sr->arg.dirop);
  64 
  65         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
  66 }
  67 
  68 void
  69 smb_post_create_directory(smb_request_t *sr)
  70 {
  71         DTRACE_SMB_1(op__CreateDirectory__done, smb_request_t *, sr);
  72 }
  73 
  74 smb_sdrc_t
  75 smb_com_create_directory(smb_request_t *sr)
  76 {
  77         int rc = 0;
  78         smb_pathname_t *pn = &sr->arg.dirop.fqi.fq_path;
  79 
  80         if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) {
  81                 smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
  82                     ERRDOS, ERROR_ACCESS_DENIED);
  83                 return (SDRC_ERROR);
  84         }
  85 
  86         smb_pathname_init(sr, pn, pn->pn_path);
  87         if (!smb_pathname_validate(sr, pn) ||
  88             !smb_validate_dirname(sr, pn)) {
  89                 return (SDRC_ERROR);
  90         }
  91 
 
 189  * USHORT ByteCount;                  Count of data bytes; min = 2
 190  * UCHAR BufferFormat;                0x04
 191  * STRING DirectoryName[];            Directory name
 192  *
 193  * The directory to be deleted cannot be the root of the share specified
 194  * by Tid.
 195  *
 196  * Server Response                    Description
 197  * ================================== =================================
 198  * UCHAR WordCount;                   Count of parameter words = 0
 199  * USHORT ByteCount;                  Count of data bytes = 0
 200  */
 201 smb_sdrc_t
 202 smb_pre_delete_directory(smb_request_t *sr)
 203 {
 204         int rc;
 205 
 206         rc = smbsr_decode_data(sr, "%S", sr,
 207             &sr->arg.dirop.fqi.fq_path.pn_path);
 208 
 209         DTRACE_SMB_2(op__DeleteDirectory__start, smb_request_t *, sr,
 210             struct dirop *, &sr->arg.dirop);
 211 
 212         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 213 }
 214 
 215 void
 216 smb_post_delete_directory(smb_request_t *sr)
 217 {
 218         DTRACE_SMB_1(op__DeleteDirectory__done, smb_request_t *, sr);
 219 }
 220 
 221 smb_sdrc_t
 222 smb_com_delete_directory(smb_request_t *sr)
 223 {
 224         int rc;
 225         uint32_t flags = 0;
 226         smb_fqi_t *fqi;
 227         smb_node_t *tnode;
 228 
 229         if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) {
 230                 smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
 231                     ERRDOS, ERROR_ACCESS_DENIED);
 232                 return (SDRC_ERROR);
 233         }
 234 
 235         fqi = &sr->arg.dirop.fqi;
 236         tnode = sr->tid_tree->t_snode;
 237 
 238         smb_pathname_init(sr, &fqi->fq_path, fqi->fq_path.pn_path);
 239         if (!smb_pathname_validate(sr, &fqi->fq_path) ||
 240             !smb_validate_dirname(sr, &fqi->fq_path)) {
 241                 return (SDRC_ERROR);
 242         }
 243 
 244         rc = smb_pathname_reduce(sr, sr->user_cr, fqi->fq_path.pn_path,
 245             tnode, tnode, &fqi->fq_dnode, fqi->fq_last_comp);
 246 
 247         if (rc != 0) {
 248                 smbsr_errno(sr, rc);
 249                 return (SDRC_ERROR);
 250         }
 251 
 252         rc = smb_fsop_lookup(sr, sr->user_cr, SMB_FOLLOW_LINKS,
 253             tnode, fqi->fq_dnode, fqi->fq_last_comp, &fqi->fq_fnode);
 254         if (rc != 0) {
 255                 if (rc == ENOENT)
 256                         smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND,
 257                             ERRDOS, ERROR_FILE_NOT_FOUND);
 258                 else
 259                         smbsr_errno(sr, rc);
 260                 smb_node_release(fqi->fq_dnode);
 261                 return (SDRC_ERROR);
 262         }
 263 
 264         /*
 265          * Delete should fail if this is the root of a share
 266          * or a DFS link
 267          */
 268         if ((fqi->fq_fnode == tnode) || smb_node_is_dfslink(fqi->fq_fnode)) {
 269                 smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
 270                     ERRDOS, ERROR_ACCESS_DENIED);
 271                 smb_node_release(fqi->fq_dnode);
 272                 smb_node_release(fqi->fq_fnode);
 273                 return (SDRC_ERROR);
 274         }
 275 
 276         if (!smb_node_is_dir(fqi->fq_fnode)) {
 277                 smbsr_error(sr, NT_STATUS_NOT_A_DIRECTORY,
 278                     ERRDOS, ERROR_PATH_NOT_FOUND);
 
 344  * UCHAR BufferFormat;                0x04
 345  * STRING DirectoryPath[];            Directory path
 346  *
 347  * Server Response                    Description
 348  * ================================== =================================
 349  *
 350  * UCHAR WordCount;                   Count of parameter words = 0
 351  * USHORT ByteCount;                  Count of data bytes = 0
 352  *
 353  * DOS clients, in particular, depend on ERRbadpath if the directory is
 354  * not found.
 355  */
 356 smb_sdrc_t
 357 smb_pre_check_directory(smb_request_t *sr)
 358 {
 359         int rc;
 360 
 361         rc = smbsr_decode_data(sr, "%S", sr,
 362             &sr->arg.dirop.fqi.fq_path.pn_path);
 363 
 364         DTRACE_SMB_2(op__CheckDirectory__start, smb_request_t *, sr,
 365             struct dirop *, &sr->arg.dirop);
 366 
 367         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 368 }
 369 
 370 void
 371 smb_post_check_directory(smb_request_t *sr)
 372 {
 373         DTRACE_SMB_1(op__CheckDirectory__done, smb_request_t *, sr);
 374 }
 375 
 376 smb_sdrc_t
 377 smb_com_check_directory(smb_request_t *sr)
 378 {
 379         int rc;
 380         smb_fqi_t *fqi;
 381         smb_node_t *tnode;
 382         smb_node_t *node;
 383         char *path;
 384         smb_pathname_t *pn;
 385 
 386         if (STYPE_ISIPC(sr->tid_tree->t_res_type)) {
 387                 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS,
 388                     ERROR_ACCESS_DENIED);
 389                 return (SDRC_ERROR);
 390         }
 391 
 392         fqi = &sr->arg.dirop.fqi;
 393         pn = &fqi->fq_path;
 
 400         smb_pathname_init(sr, pn, pn->pn_path);
 401         if (!smb_pathname_validate(sr, pn) ||
 402             !smb_validate_dirname(sr, pn)) {
 403                 return (SDRC_ERROR);
 404         }
 405 
 406         path = pn->pn_path;
 407         tnode = sr->tid_tree->t_snode;
 408 
 409         rc = smb_pathname_reduce(sr, sr->user_cr, path, tnode, tnode,
 410             &fqi->fq_dnode, fqi->fq_last_comp);
 411         if (rc != 0) {
 412                 smbsr_errno(sr, rc);
 413                 return (SDRC_ERROR);
 414         }
 415 
 416         rc = smb_fsop_lookup(sr, sr->user_cr, SMB_FOLLOW_LINKS,
 417             tnode, fqi->fq_dnode, fqi->fq_last_comp, &fqi->fq_fnode);
 418         smb_node_release(fqi->fq_dnode);
 419         if (rc != 0) {
 420                 if (rc == ENOENT)
 421                         smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND,
 422                             ERRDOS, ERROR_PATH_NOT_FOUND);
 423                 else
 424                         smbsr_errno(sr, rc);
 425                 return (SDRC_ERROR);
 426         }
 427 
 428         node = fqi->fq_fnode;
 429         if (!smb_node_is_dir(node)) {
 430                 smbsr_error(sr, NT_STATUS_NOT_A_DIRECTORY,
 431                     ERRDOS, ERROR_PATH_NOT_FOUND);
 432                 smb_node_release(node);
 433                 return (SDRC_ERROR);
 434         }
 435 
 436         if ((sr->smb_flg2 & SMB_FLAGS2_DFS) && smb_node_is_dfslink(node)) {
 437                 smbsr_error(sr, NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
 438                 smb_node_release(node);
 439                 return (SDRC_ERROR);
 440         }
 441 
 442         rc = smb_fsop_access(sr, sr->user_cr, node, FILE_TRAVERSE);
 443 
 | 
 
 
   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 2010 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  *
  25  * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
  26  */
  27 
  28 #include <smbsrv/smb_kproto.h>
  29 #include <smbsrv/smbinfo.h>
  30 #include <smbsrv/smb_fsops.h>
  31 
  32 /*
  33  * The create directory message is sent to create a new directory.  The
  34  * appropriate Tid and additional pathname are passed.  The directory must
  35  * not exist for it to be created.
  36  *
  37  * Client Request                     Description
  38  * ================================== =================================
  39  * UCHAR WordCount;                   Count of parameter words = 0
  40  * USHORT ByteCount;                  Count of data bytes; min = 2
  41  * UCHAR BufferFormat;                0x04
  42  * STRING DirectoryName[];            Directory name
  43  *
  44  * Servers require clients to have at least create permission for the
  45  * subtree containing the directory in order to create a new directory.
  46  * The creator's access rights to the new directory are be determined by
  47  * local policy on the server.
  48  *
  49  * Server Response                    Description
  50  * ================================== =================================
  51  * UCHAR WordCount;                   Count of parameter words = 0
  52  * USHORT ByteCount;                  Count of data bytes = 0
  53  */
  54 smb_sdrc_t
  55 smb_pre_create_directory(smb_request_t *sr)
  56 {
  57         int rc;
  58 
  59         rc = smbsr_decode_data(sr, "%S", sr,
  60             &sr->arg.dirop.fqi.fq_path.pn_path);
  61 
  62         DTRACE_SMB_START(op__CreateDirectory, smb_request_t *, sr);
  63 
  64         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
  65 }
  66 
  67 void
  68 smb_post_create_directory(smb_request_t *sr)
  69 {
  70         DTRACE_SMB_DONE(op__CreateDirectory, smb_request_t *, sr);
  71 }
  72 
  73 smb_sdrc_t
  74 smb_com_create_directory(smb_request_t *sr)
  75 {
  76         int rc = 0;
  77         smb_pathname_t *pn = &sr->arg.dirop.fqi.fq_path;
  78 
  79         if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) {
  80                 smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
  81                     ERRDOS, ERROR_ACCESS_DENIED);
  82                 return (SDRC_ERROR);
  83         }
  84 
  85         smb_pathname_init(sr, pn, pn->pn_path);
  86         if (!smb_pathname_validate(sr, pn) ||
  87             !smb_validate_dirname(sr, pn)) {
  88                 return (SDRC_ERROR);
  89         }
  90 
 
 188  * USHORT ByteCount;                  Count of data bytes; min = 2
 189  * UCHAR BufferFormat;                0x04
 190  * STRING DirectoryName[];            Directory name
 191  *
 192  * The directory to be deleted cannot be the root of the share specified
 193  * by Tid.
 194  *
 195  * Server Response                    Description
 196  * ================================== =================================
 197  * UCHAR WordCount;                   Count of parameter words = 0
 198  * USHORT ByteCount;                  Count of data bytes = 0
 199  */
 200 smb_sdrc_t
 201 smb_pre_delete_directory(smb_request_t *sr)
 202 {
 203         int rc;
 204 
 205         rc = smbsr_decode_data(sr, "%S", sr,
 206             &sr->arg.dirop.fqi.fq_path.pn_path);
 207 
 208         DTRACE_SMB_START(op__DeleteDirectory, smb_request_t *, sr);
 209 
 210         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 211 }
 212 
 213 void
 214 smb_post_delete_directory(smb_request_t *sr)
 215 {
 216         DTRACE_SMB_DONE(op__DeleteDirectory, smb_request_t *, sr);
 217 }
 218 
 219 smb_sdrc_t
 220 smb_com_delete_directory(smb_request_t *sr)
 221 {
 222         int rc;
 223         uint32_t flags = 0;
 224         smb_fqi_t *fqi;
 225         smb_node_t *tnode;
 226 
 227         if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) {
 228                 smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
 229                     ERRDOS, ERROR_ACCESS_DENIED);
 230                 return (SDRC_ERROR);
 231         }
 232 
 233         fqi = &sr->arg.dirop.fqi;
 234         tnode = sr->tid_tree->t_snode;
 235 
 236         smb_pathname_init(sr, &fqi->fq_path, fqi->fq_path.pn_path);
 237         if (!smb_pathname_validate(sr, &fqi->fq_path) ||
 238             !smb_validate_dirname(sr, &fqi->fq_path)) {
 239                 return (SDRC_ERROR);
 240         }
 241 
 242         rc = smb_pathname_reduce(sr, sr->user_cr, fqi->fq_path.pn_path,
 243             tnode, tnode, &fqi->fq_dnode, fqi->fq_last_comp);
 244 
 245         if (rc != 0) {
 246                 smbsr_errno(sr, rc);
 247                 return (SDRC_ERROR);
 248         }
 249 
 250         rc = smb_fsop_lookup(sr, sr->user_cr, SMB_FOLLOW_LINKS,
 251             tnode, fqi->fq_dnode, fqi->fq_last_comp, &fqi->fq_fnode);
 252         if (rc != 0) {
 253                 smbsr_errno(sr, rc);
 254                 smb_node_release(fqi->fq_dnode);
 255                 return (SDRC_ERROR);
 256         }
 257 
 258         /*
 259          * Delete should fail if this is the root of a share
 260          * or a DFS link
 261          */
 262         if ((fqi->fq_fnode == tnode) || smb_node_is_dfslink(fqi->fq_fnode)) {
 263                 smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
 264                     ERRDOS, ERROR_ACCESS_DENIED);
 265                 smb_node_release(fqi->fq_dnode);
 266                 smb_node_release(fqi->fq_fnode);
 267                 return (SDRC_ERROR);
 268         }
 269 
 270         if (!smb_node_is_dir(fqi->fq_fnode)) {
 271                 smbsr_error(sr, NT_STATUS_NOT_A_DIRECTORY,
 272                     ERRDOS, ERROR_PATH_NOT_FOUND);
 
 338  * UCHAR BufferFormat;                0x04
 339  * STRING DirectoryPath[];            Directory path
 340  *
 341  * Server Response                    Description
 342  * ================================== =================================
 343  *
 344  * UCHAR WordCount;                   Count of parameter words = 0
 345  * USHORT ByteCount;                  Count of data bytes = 0
 346  *
 347  * DOS clients, in particular, depend on ERRbadpath if the directory is
 348  * not found.
 349  */
 350 smb_sdrc_t
 351 smb_pre_check_directory(smb_request_t *sr)
 352 {
 353         int rc;
 354 
 355         rc = smbsr_decode_data(sr, "%S", sr,
 356             &sr->arg.dirop.fqi.fq_path.pn_path);
 357 
 358         DTRACE_SMB_START(op__CheckDirectory, smb_request_t *, sr);
 359 
 360         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 361 }
 362 
 363 void
 364 smb_post_check_directory(smb_request_t *sr)
 365 {
 366         DTRACE_SMB_DONE(op__CheckDirectory, smb_request_t *, sr);
 367 }
 368 
 369 smb_sdrc_t
 370 smb_com_check_directory(smb_request_t *sr)
 371 {
 372         int rc;
 373         smb_fqi_t *fqi;
 374         smb_node_t *tnode;
 375         smb_node_t *node;
 376         char *path;
 377         smb_pathname_t *pn;
 378 
 379         if (STYPE_ISIPC(sr->tid_tree->t_res_type)) {
 380                 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS,
 381                     ERROR_ACCESS_DENIED);
 382                 return (SDRC_ERROR);
 383         }
 384 
 385         fqi = &sr->arg.dirop.fqi;
 386         pn = &fqi->fq_path;
 
 393         smb_pathname_init(sr, pn, pn->pn_path);
 394         if (!smb_pathname_validate(sr, pn) ||
 395             !smb_validate_dirname(sr, pn)) {
 396                 return (SDRC_ERROR);
 397         }
 398 
 399         path = pn->pn_path;
 400         tnode = sr->tid_tree->t_snode;
 401 
 402         rc = smb_pathname_reduce(sr, sr->user_cr, path, tnode, tnode,
 403             &fqi->fq_dnode, fqi->fq_last_comp);
 404         if (rc != 0) {
 405                 smbsr_errno(sr, rc);
 406                 return (SDRC_ERROR);
 407         }
 408 
 409         rc = smb_fsop_lookup(sr, sr->user_cr, SMB_FOLLOW_LINKS,
 410             tnode, fqi->fq_dnode, fqi->fq_last_comp, &fqi->fq_fnode);
 411         smb_node_release(fqi->fq_dnode);
 412         if (rc != 0) {
 413                 smbsr_errno(sr, rc);
 414                 return (SDRC_ERROR);
 415         }
 416 
 417         node = fqi->fq_fnode;
 418         if (!smb_node_is_dir(node)) {
 419                 smbsr_error(sr, NT_STATUS_NOT_A_DIRECTORY,
 420                     ERRDOS, ERROR_PATH_NOT_FOUND);
 421                 smb_node_release(node);
 422                 return (SDRC_ERROR);
 423         }
 424 
 425         if ((sr->smb_flg2 & SMB_FLAGS2_DFS) && smb_node_is_dfslink(node)) {
 426                 smbsr_error(sr, NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
 427                 smb_node_release(node);
 428                 return (SDRC_ERROR);
 429         }
 430 
 431         rc = smb_fsop_access(sr, sr->user_cr, node, FILE_TRAVERSE);
 432 
 |