LCOV - code coverage report
Current view: top level - source4/torture/smb2 - max_allowed.c (source / functions) Hit Total Coverage
Test: coverage report for master 70ed9daf Lines: 90 102 88.2 %
Date: 2024-01-11 09:59:51 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}};
      37           0 :         int i;
      38           5 :         bool ret = true;
      39           0 :         NTSTATUS status;
      40           0 :         union smb_fileinfo q;
      41           5 :         const char *owner_sid = NULL;
      42           0 :         bool has_restore_privilege, has_backup_privilege, has_system_security_privilege;
      43             : 
      44           5 :         mem_ctx = talloc_init("torture_maximum_allowed");
      45           5 :         torture_assert_goto(tctx, mem_ctx != NULL, ret, done,
      46             :                             "talloc allocation failed\n");
      47             : 
      48           5 :         if (!torture_setting_bool(tctx, "sacl_support", true))
      49           0 :                 torture_warning(tctx, "Skipping SACL related tests!\n");
      50             : 
      51           5 :         sd = security_descriptor_dacl_create(mem_ctx,
      52             :             0, NULL, NULL,
      53             :             SID_NT_AUTHENTICATED_USERS,
      54             :             SEC_ACE_TYPE_ACCESS_ALLOWED,
      55             :             SEC_RIGHTS_FILE_READ,
      56             :             0, NULL);
      57           5 :         torture_assert_goto(tctx, sd != NULL, ret, done,
      58             :                             "security descriptor creation failed\n");
      59             : 
      60             :         /* Blank slate */
      61           5 :         smb2_util_unlink(tree, MAXIMUM_ALLOWED_FILE);
      62             : 
      63             :         /* create initial file with restrictive SD */
      64           5 :         io.in.desired_access = SEC_RIGHTS_FILE_ALL;
      65           5 :         io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
      66           5 :         io.in.create_disposition = NTCREATEX_DISP_CREATE;
      67           5 :         io.in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS;
      68           5 :         io.in.fname = MAXIMUM_ALLOWED_FILE;
      69           5 :         io.in.sec_desc = sd;
      70             : 
      71           5 :         status = smb2_create(tree, mem_ctx, &io);
      72           5 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
      73             :                 talloc_asprintf(tctx, "Incorrect status %s - should be %s\n",
      74             :                                 nt_errstr(status), nt_errstr(NT_STATUS_OK)));
      75           5 :         fnum = io.out.file.handle;
      76             : 
      77             :         /* the correct answers for this test depends on whether the
      78             :            user has restore privileges. To find that out we first need
      79             :            to know our SID - get it from the owner_sid of the file we
      80             :            just created */
      81           5 :         q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
      82           5 :         q.query_secdesc.in.file.handle = fnum;
      83           5 :         q.query_secdesc.in.secinfo_flags = SECINFO_DACL | SECINFO_OWNER;
      84           5 :         status = smb2_getinfo_file(tree, tctx, &q);
      85           5 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
      86             :                 talloc_asprintf(tctx, "Incorrect status %s - should be %s\n",
      87             :                                 nt_errstr(status), nt_errstr(NT_STATUS_OK)));
      88           5 :         sd_orig = q.query_secdesc.out.sd;
      89             : 
      90           5 :         owner_sid = dom_sid_string(tctx, sd_orig->owner_sid);
      91             : 
      92           5 :         status = torture_smb2_check_privilege(tree,
      93             :                                          owner_sid,
      94             :                                          sec_privilege_name(SEC_PRIV_RESTORE));
      95           5 :         has_restore_privilege = NT_STATUS_IS_OK(status);
      96           5 :         torture_comment(tctx, "Checked SEC_PRIV_RESTORE for %s - %s\n",
      97             :                         owner_sid,
      98             :                         has_restore_privilege?"Yes":"No");
      99             : 
     100           5 :         status = torture_smb2_check_privilege(tree,
     101             :                                          owner_sid,
     102             :                                          sec_privilege_name(SEC_PRIV_BACKUP));
     103           5 :         has_backup_privilege = NT_STATUS_IS_OK(status);
     104           5 :         torture_comment(tctx, "Checked SEC_PRIV_BACKUP for %s - %s\n",
     105             :                         owner_sid,
     106             :                         has_backup_privilege?"Yes":"No");
     107             : 
     108           5 :         status = torture_smb2_check_privilege(tree,
     109             :                                          owner_sid,
     110             :                                          sec_privilege_name(SEC_PRIV_SECURITY));
     111           5 :         has_system_security_privilege = NT_STATUS_IS_OK(status);
     112           5 :         torture_comment(tctx, "Checked SEC_PRIV_SECURITY for %s - %s\n",
     113             :                         owner_sid,
     114             :                         has_system_security_privilege?"Yes":"No");
     115             : 
     116           5 :         smb2_util_close(tree, fnum);
     117             : 
     118          40 :         for (i = 0; i < 32; i++) {
     119          40 :                 uint32_t mask = SEC_FLAG_MAXIMUM_ALLOWED | (1u << i);
     120             :                 /*
     121             :                  * SEC_GENERIC_EXECUTE is a complete subset of
     122             :                  * SEC_GENERIC_READ when mapped to specific bits,
     123             :                  * so we need to include it in the basic OK mask.
     124             :                  */
     125          40 :                 uint32_t ok_mask = SEC_RIGHTS_FILE_READ | SEC_GENERIC_READ | SEC_GENERIC_EXECUTE |
     126             :                         SEC_STD_DELETE | SEC_STD_WRITE_DAC;
     127             : 
     128             :                 /*
     129             :                  * Now SEC_RIGHTS_PRIV_RESTORE and SEC_RIGHTS_PRIV_BACKUP
     130             :                  * don't include any generic bits (they're used directly
     131             :                  * in the fileserver where the generic bits have already
     132             :                  * been mapped into file specific bits) we need to add the
     133             :                  * generic bits to the ok_mask when we have these privileges.
     134             :                  */
     135          40 :                 if (has_restore_privilege) {
     136           6 :                         ok_mask |= SEC_RIGHTS_PRIV_RESTORE|SEC_GENERIC_WRITE;
     137             :                 }
     138          40 :                 if (has_backup_privilege) {
     139           6 :                         ok_mask |= SEC_RIGHTS_PRIV_BACKUP|SEC_GENERIC_READ;
     140             :                 }
     141          40 :                 if (has_system_security_privilege) {
     142           6 :                         ok_mask |= SEC_FLAG_SYSTEM_SECURITY;
     143             :                 }
     144             : 
     145             :                 /* Skip all SACL related tests. */
     146          40 :                 if ((!torture_setting_bool(tctx, "sacl_support", true)) &&
     147           0 :                     (mask & SEC_FLAG_SYSTEM_SECURITY))
     148           0 :                         continue;
     149             : 
     150          40 :                 io = (struct smb2_create){0};
     151          40 :                 io.in.desired_access = mask;
     152          40 :                 io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
     153          40 :                 io.in.create_disposition = NTCREATEX_DISP_OPEN;
     154          40 :                 io.in.impersonation_level =
     155             :                     NTCREATEX_IMPERSONATION_ANONYMOUS;
     156          40 :                 io.in.fname = MAXIMUM_ALLOWED_FILE;
     157             : 
     158          40 :                 status = smb2_create(tree, mem_ctx, &io);
     159          40 :                 if (mask & ok_mask ||
     160             :                     mask == SEC_FLAG_MAXIMUM_ALLOWED) {
     161          14 :                         torture_assert_ntstatus_ok_goto(tctx, status, ret,
     162             :                                 done, talloc_asprintf(tctx,
     163             :                                 "Incorrect status %s - should be %s\n",
     164             :                                 nt_errstr(status), nt_errstr(NT_STATUS_OK)));
     165             :                 } else {
     166          26 :                         if (mask & SEC_FLAG_SYSTEM_SECURITY) {
     167           0 :                                 torture_assert_ntstatus_equal_goto(tctx,
     168             :                                         status, NT_STATUS_PRIVILEGE_NOT_HELD,
     169             :                                         ret, done, talloc_asprintf(tctx,
     170             :                                         "Incorrect status %s - should be %s\n",
     171             :                                         nt_errstr(status),
     172             :                                         nt_errstr(NT_STATUS_PRIVILEGE_NOT_HELD)));
     173             :                         } else {
     174          26 :                                 torture_assert_ntstatus_equal_goto(tctx,
     175             :                                         status, NT_STATUS_ACCESS_DENIED,
     176             :                                         ret, done, talloc_asprintf(tctx,
     177             :                                         "Incorrect status %s - should be %s\n",
     178             :                                         nt_errstr(status),
     179             :                                         nt_errstr(NT_STATUS_ACCESS_DENIED)));
     180             :                         }
     181             :                 }
     182             : 
     183          35 :                 fnum = io.out.file.handle;
     184             : 
     185          35 :                 smb2_util_close(tree, fnum);
     186             :         }
     187             : 
     188           0 :  done:
     189           5 :         smb2_util_unlink(tree, MAXIMUM_ALLOWED_FILE);
     190           5 :         talloc_free(mem_ctx);
     191           5 :         return ret;
     192             : }
     193             : 
     194           5 : static bool torture_smb2_read_only_file(struct torture_context *tctx,
     195             :                                         struct smb2_tree *tree)
     196             : {
     197           0 :         struct smb2_create c;
     198           5 :         struct smb2_handle h = {{0}};
     199           5 :         bool ret = true;
     200           0 :         NTSTATUS status;
     201             : 
     202           5 :         smb2_deltree(tree, MAXIMUM_ALLOWED_FILE);
     203             : 
     204           5 :         c = (struct smb2_create) {
     205             :                 .in.desired_access = SEC_RIGHTS_FILE_ALL,
     206             :                 .in.file_attributes = FILE_ATTRIBUTE_READONLY,
     207             :                 .in.create_disposition = NTCREATEX_DISP_CREATE,
     208             :                 .in.fname = MAXIMUM_ALLOWED_FILE,
     209             :         };
     210             : 
     211           5 :         status = smb2_create(tree, tctx, &c);
     212           5 :         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
     213             :                                         "smb2_create failed\n");
     214           5 :         h = c.out.file.handle;
     215           5 :         smb2_util_close(tree, h);
     216           5 :         ZERO_STRUCT(h);
     217             : 
     218           5 :         c = (struct smb2_create) {
     219             :                 .in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED,
     220             :                 .in.file_attributes = FILE_ATTRIBUTE_READONLY,
     221             :                 .in.create_disposition = NTCREATEX_DISP_OPEN,
     222             :                 .in.fname = MAXIMUM_ALLOWED_FILE,
     223             :         };
     224             : 
     225           5 :         status = smb2_create(tree, tctx, &c);
     226           5 :         torture_assert_ntstatus_ok_goto(
     227             :                 tctx, status, ret, done,
     228             :                 "Failed to open READ-ONLY file with SEC_FLAG_MAXIMUM_ALLOWED\n");
     229           5 :         h = c.out.file.handle;
     230           5 :         smb2_util_close(tree, h);
     231           5 :         ZERO_STRUCT(h);
     232             : 
     233           5 : done:
     234           5 :         if (!smb2_util_handle_empty(h)) {
     235           0 :                 smb2_util_close(tree, h);
     236             :         }
     237           5 :         smb2_deltree(tree, MAXIMUM_ALLOWED_FILE);
     238           5 :         return ret;
     239             : }
     240             : 
     241        2358 : struct torture_suite *torture_smb2_max_allowed(TALLOC_CTX *ctx)
     242             : {
     243        2358 :         struct torture_suite *suite = torture_suite_create(ctx, "maximum_allowed");
     244             : 
     245        2358 :         torture_suite_add_1smb2_test(suite, "maximum_allowed", torture_smb2_maximum_allowed);
     246        2358 :         torture_suite_add_1smb2_test(suite, "read_only", torture_smb2_read_only_file);
     247        2358 :         return suite;
     248             : }

Generated by: LCOV version 1.14