LCOV - code coverage report
Current view: top level - source4/torture/smb2 - max_allowed.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 107 120 89.2 %
Date: 2024-02-28 12:06:22 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    SMB torture tester - deny mode scanning functions
       4             :    Copyright (C) Andrew Tridgell 2001
       5             :    Copyright (C) David Mulder 2019
       6             : 
       7             :    This program is free software; you can redistribute it and/or modify
       8             :    it under the terms of the GNU General Public License as published by
       9             :    the Free Software Foundation; either version 3 of the License, or
      10             :    (at your option) any later version.
      11             : 
      12             :    This program 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 the
      15             :    GNU General Public License for more details.
      16             : 
      17             :    You should have received a copy of the GNU General Public License
      18             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      19             : */
      20             : 
      21             : #include "includes.h"
      22             : #include "system/filesys.h"
      23             : #include "libcli/smb2/smb2.h"
      24             : #include "libcli/smb2/smb2_calls.h"
      25             : #include "libcli/security/security.h"
      26             : #include "torture/util.h"
      27             : #include "torture/smb2/proto.h"
      28             : 
      29             : #define MAXIMUM_ALLOWED_FILE    "torture_maximum_allowed"
      30           5 : static bool torture_smb2_maximum_allowed(struct torture_context *tctx,
      31             :                                          struct smb2_tree *tree)
      32             : {
      33           5 :         struct security_descriptor *sd = NULL, *sd_orig = NULL;
      34           5 :         struct smb2_create io = {0};
      35           5 :         TALLOC_CTX *mem_ctx = NULL;
      36           5 :         struct smb2_handle fnum = {{0}}, fnum1 = {{0}};
      37           0 :         int i;
      38           5 :         bool ret = true;
      39           0 :         NTSTATUS status;
      40           0 :         union smb_fileinfo q;
      41           0 :         union smb_setfileinfo set;
      42           5 :         const char *owner_sid = NULL;
      43           0 :         bool has_restore_privilege, has_backup_privilege, has_system_security_privilege;
      44             : 
      45           5 :         mem_ctx = talloc_init("torture_maximum_allowed");
      46           5 :         torture_assert_goto(tctx, mem_ctx != NULL, ret, done,
      47             :                             "talloc allocation failed\n");
      48             : 
      49           5 :         if (!torture_setting_bool(tctx, "sacl_support", true))
      50           0 :                 torture_warning(tctx, "Skipping SACL related tests!\n");
      51             : 
      52           5 :         sd = security_descriptor_dacl_create(mem_ctx,
      53             :             0, NULL, NULL,
      54             :             SID_NT_AUTHENTICATED_USERS,
      55             :             SEC_ACE_TYPE_ACCESS_ALLOWED,
      56             :             SEC_RIGHTS_FILE_READ,
      57             :             0, NULL);
      58           5 :         torture_assert_goto(tctx, sd != NULL, ret, done,
      59             :                             "security descriptor creation failed\n");
      60             : 
      61             :         /* Blank slate */
      62           5 :         smb2_util_unlink(tree, MAXIMUM_ALLOWED_FILE);
      63             : 
      64             :         /* create initial file with restrictive SD */
      65           5 :         io.in.desired_access = SEC_RIGHTS_FILE_ALL;
      66           5 :         io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
      67           5 :         io.in.create_disposition = NTCREATEX_DISP_CREATE;
      68           5 :         io.in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS;
      69           5 :         io.in.fname = MAXIMUM_ALLOWED_FILE;
      70           5 :         io.in.sec_desc = sd;
      71             : 
      72           5 :         status = smb2_create(tree, mem_ctx, &io);
      73           5 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
      74             :                 talloc_asprintf(tctx, "Incorrect status %s - should be %s\n",
      75             :                                 nt_errstr(status), nt_errstr(NT_STATUS_OK)));
      76           5 :         fnum = io.out.file.handle;
      77             : 
      78             :         /* the correct answers for this test depends on whether the
      79             :            user has restore privileges. To find that out we first need
      80             :            to know our SID - get it from the owner_sid of the file we
      81             :            just created */
      82           5 :         q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
      83           5 :         q.query_secdesc.in.file.handle = fnum;
      84           5 :         q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
      85           5 :         status = smb2_getinfo_file(tree, tctx, &q);
      86           5 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, set_sd,
      87             :                 talloc_asprintf(tctx, "Incorrect status %s - should be %s\n",
      88             :                                 nt_errstr(status), nt_errstr(NT_STATUS_OK)));
      89           5 :         sd_orig = q.query_secdesc.out.sd;
      90             : 
      91           5 :         owner_sid = dom_sid_string(tctx, sd_orig->owner_sid);
      92             : 
      93           5 :         status = torture_smb2_check_privilege(tree,
      94             :                                          owner_sid,
      95             :                                          sec_privilege_name(SEC_PRIV_RESTORE));
      96           5 :         has_restore_privilege = NT_STATUS_IS_OK(status);
      97           5 :         torture_comment(tctx, "Checked SEC_PRIV_RESTORE for %s - %s\n",
      98             :                         owner_sid,
      99             :                         has_restore_privilege?"Yes":"No");
     100             : 
     101           5 :         status = torture_smb2_check_privilege(tree,
     102             :                                          owner_sid,
     103             :                                          sec_privilege_name(SEC_PRIV_BACKUP));
     104           5 :         has_backup_privilege = NT_STATUS_IS_OK(status);
     105           5 :         torture_comment(tctx, "Checked SEC_PRIV_BACKUP for %s - %s\n",
     106             :                         owner_sid,
     107             :                         has_backup_privilege?"Yes":"No");
     108             : 
     109           5 :         status = torture_smb2_check_privilege(tree,
     110             :                                          owner_sid,
     111             :                                          sec_privilege_name(SEC_PRIV_SECURITY));
     112           5 :         has_system_security_privilege = NT_STATUS_IS_OK(status);
     113           5 :         torture_comment(tctx, "Checked SEC_PRIV_SECURITY for %s - %s\n",
     114             :                         owner_sid,
     115             :                         has_system_security_privilege?"Yes":"No");
     116             : 
     117           5 :         smb2_util_close(tree, fnum);
     118             : 
     119          40 :         for (i = 0; i < 32; i++) {
     120          40 :                 uint32_t mask = SEC_FLAG_MAXIMUM_ALLOWED | (1u << i);
     121             :                 /*
     122             :                  * SEC_GENERIC_EXECUTE is a complete subset of
     123             :                  * SEC_GENERIC_READ when mapped to specific bits,
     124             :                  * so we need to include it in the basic OK mask.
     125             :                  */
     126          40 :                 uint32_t ok_mask = SEC_RIGHTS_FILE_READ | SEC_GENERIC_READ | SEC_GENERIC_EXECUTE |
     127             :                         SEC_STD_DELETE | SEC_STD_WRITE_DAC;
     128             : 
     129             :                 /*
     130             :                  * Now SEC_RIGHTS_PRIV_RESTORE and SEC_RIGHTS_PRIV_BACKUP
     131             :                  * don't include any generic bits (they're used directly
     132             :                  * in the fileserver where the generic bits have already
     133             :                  * been mapped into file specific bits) we need to add the
     134             :                  * generic bits to the ok_mask when we have these privileges.
     135             :                  */
     136          40 :                 if (has_restore_privilege) {
     137           6 :                         ok_mask |= SEC_RIGHTS_PRIV_RESTORE|SEC_GENERIC_WRITE;
     138             :                 }
     139          40 :                 if (has_backup_privilege) {
     140           6 :                         ok_mask |= SEC_RIGHTS_PRIV_BACKUP|SEC_GENERIC_READ;
     141             :                 }
     142          40 :                 if (has_system_security_privilege) {
     143           6 :                         ok_mask |= SEC_FLAG_SYSTEM_SECURITY;
     144             :                 }
     145             : 
     146             :                 /* Skip all SACL related tests. */
     147          40 :                 if ((!torture_setting_bool(tctx, "sacl_support", true)) &&
     148           0 :                     (mask & SEC_FLAG_SYSTEM_SECURITY))
     149           0 :                         continue;
     150             : 
     151          40 :                 io = (struct smb2_create){0};
     152          40 :                 io.in.desired_access = mask;
     153          40 :                 io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     154          40 :                 io.in.create_disposition = NTCREATEX_DISP_OPEN;
     155          40 :                 io.in.impersonation_level =
     156             :                     NTCREATEX_IMPERSONATION_ANONYMOUS;
     157          40 :                 io.in.fname = MAXIMUM_ALLOWED_FILE;
     158             : 
     159          40 :                 status = smb2_create(tree, mem_ctx, &io);
     160          40 :                 if (mask & ok_mask ||
     161             :                     mask == SEC_FLAG_MAXIMUM_ALLOWED) {
     162          14 :                         torture_assert_ntstatus_ok_goto(tctx, status, ret,
     163             :                                 set_sd, talloc_asprintf(tctx,
     164             :                                 "Incorrect status %s - should be %s\n",
     165             :                                 nt_errstr(status), nt_errstr(NT_STATUS_OK)));
     166             :                 } else {
     167          26 :                         if (mask & SEC_FLAG_SYSTEM_SECURITY) {
     168           0 :                                 torture_assert_ntstatus_equal_goto(tctx,
     169             :                                         status, NT_STATUS_PRIVILEGE_NOT_HELD,
     170             :                                         ret, set_sd, talloc_asprintf(tctx,
     171             :                                         "Incorrect status %s - should be %s\n",
     172             :                                         nt_errstr(status),
     173             :                                         nt_errstr(NT_STATUS_PRIVILEGE_NOT_HELD)));
     174             :                         } else {
     175          26 :                                 torture_assert_ntstatus_equal_goto(tctx,
     176             :                                         status, NT_STATUS_ACCESS_DENIED,
     177             :                                         ret, set_sd, talloc_asprintf(tctx,
     178             :                                         "Incorrect status %s - should be %s\n",
     179             :                                         nt_errstr(status),
     180             :                                         nt_errstr(NT_STATUS_ACCESS_DENIED)));
     181             :                         }
     182             :                 }
     183             : 
     184          35 :                 fnum = io.out.file.handle;
     185             : 
     186          35 :                 smb2_util_close(tree, fnum);
     187             :         }
     188             : 
     189           0 : set_sd:
     190           5 :         io.in.desired_access = SEC_STD_WRITE_DAC;
     191           5 :         io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     192           5 :         io.in.create_disposition = NTCREATEX_DISP_OPEN;
     193           5 :         io.in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS;
     194           5 :         io.in.fname = MAXIMUM_ALLOWED_FILE;
     195             : 
     196           5 :         status = smb2_create(tree, mem_ctx, &io);
     197           5 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
     198             :                 talloc_asprintf(tctx, "Incorrect status %s - should be %s\n",
     199             :                                 nt_errstr(status), nt_errstr(NT_STATUS_OK)));
     200           5 :         fnum1 = io.out.file.handle;
     201             : 
     202           5 :         sd = security_descriptor_dacl_create(tctx,
     203             :                                         0, NULL, NULL,
     204             :                                         SID_NT_AUTHENTICATED_USERS,
     205             :                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
     206             :                                         SEC_STD_DELETE,
     207             :                                         0,
     208             :                                         NULL);
     209           5 :         set.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
     210           5 :         set.set_secdesc.in.file.handle = fnum1;
     211           5 :         set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
     212           5 :         set.set_secdesc.in.sd = sd;
     213             : 
     214           5 :         status = smb2_setinfo_file(tree, &set);
     215           5 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
     216             :                 talloc_asprintf(tctx, "Incorrect status %s - should be %s\n",
     217             :                                 nt_errstr(status), nt_errstr(NT_STATUS_OK)));
     218             : 
     219           5 :  done:
     220           5 :         smb2_util_close(tree, fnum1);
     221           5 :         smb2_util_unlink(tree, MAXIMUM_ALLOWED_FILE);
     222           5 :         talloc_free(mem_ctx);
     223           5 :         return ret;
     224             : }
     225             : 
     226           5 : static bool torture_smb2_read_only_file(struct torture_context *tctx,
     227             :                                         struct smb2_tree *tree)
     228             : {
     229           0 :         struct smb2_create c;
     230           5 :         struct smb2_handle h = {{0}};
     231           5 :         bool ret = true;
     232           0 :         NTSTATUS status;
     233             : 
     234           5 :         smb2_deltree(tree, MAXIMUM_ALLOWED_FILE);
     235             : 
     236           5 :         c = (struct smb2_create) {
     237             :                 .in.desired_access = SEC_RIGHTS_FILE_ALL,
     238             :                 .in.file_attributes = FILE_ATTRIBUTE_READONLY,
     239             :                 .in.create_disposition = NTCREATEX_DISP_CREATE,
     240             :                 .in.fname = MAXIMUM_ALLOWED_FILE,
     241             :         };
     242             : 
     243           5 :         status = smb2_create(tree, tctx, &c);
     244           5 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
     245             :                                         "smb2_create failed\n");
     246           5 :         h = c.out.file.handle;
     247           5 :         smb2_util_close(tree, h);
     248           5 :         ZERO_STRUCT(h);
     249             : 
     250           5 :         c = (struct smb2_create) {
     251             :                 .in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED,
     252             :                 .in.file_attributes = FILE_ATTRIBUTE_READONLY,
     253             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
     254             :                 .in.fname = MAXIMUM_ALLOWED_FILE,
     255             :         };
     256             : 
     257           5 :         status = smb2_create(tree, tctx, &c);
     258           5 :         torture_assert_ntstatus_ok_goto(
     259             :                 tctx, status, ret, done,
     260             :                 "Failed to open READ-ONLY file with SEC_FLAG_MAXIMUM_ALLOWED\n");
     261           5 :         h = c.out.file.handle;
     262           5 :         smb2_util_close(tree, h);
     263           5 :         ZERO_STRUCT(h);
     264             : 
     265           5 : done:
     266           5 :         if (!smb2_util_handle_empty(h)) {
     267           0 :                 smb2_util_close(tree, h);
     268             :         }
     269           5 :         smb2_deltree(tree, MAXIMUM_ALLOWED_FILE);
     270           5 :         return ret;
     271             : }
     272             : 
     273        2379 : struct torture_suite *torture_smb2_max_allowed(TALLOC_CTX *ctx)
     274             : {
     275        2379 :         struct torture_suite *suite = torture_suite_create(ctx, "maximum_allowed");
     276             : 
     277        2379 :         torture_suite_add_1smb2_test(suite, "maximum_allowed", torture_smb2_maximum_allowed);
     278        2379 :         torture_suite_add_1smb2_test(suite, "read_only", torture_smb2_read_only_file);
     279        2379 :         return suite;
     280             : }

Generated by: LCOV version 1.14