LCOV - code coverage report
Current view: top level - source3/modules - nfs4acl_xattr_ndr.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 105 140 75.0 %
Date: 2024-04-21 15:09:00 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Convert NFSv4 acls stored per http://www.suse.de/~agruen/nfs4acl/ to NT acls and vice versa.
       3             :  *
       4             :  * Copyright (C) Jiri Sasek, 2007
       5             :  * based on the foobar.c module which is copyrighted by Volker Lendecke
       6             :  * based on pvfs_acl_nfs4.c  Copyright (C) Andrew Tridgell 2006
       7             :  *
       8             :  * based on vfs_fake_acls:
       9             :  * Copyright (C) Tim Potter, 1999-2000
      10             :  * Copyright (C) Alexander Bokovoy, 2002
      11             :  * Copyright (C) Andrew Bartlett, 2002,2012
      12             :  * Copyright (C) Ralph Boehme 2017
      13             :  *
      14             :  * This program is free software; you can redistribute it and/or modify
      15             :  * it under the terms of the GNU General Public License as published by
      16             :  * the Free Software Foundation; either version 3 of the License, or
      17             :  * (at your option) any later version.
      18             :  *
      19             :  * This program is distributed in the hope that it will be useful,
      20             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      21             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      22             :  * GNU General Public License for more details.
      23             :  *
      24             :  * You should have received a copy of the GNU General Public License
      25             :  * along with this program; if not, see <http://www.gnu.org/licenses/>.
      26             :  *
      27             :  */
      28             : 
      29             : #include "includes.h"
      30             : #include "system/filesys.h"
      31             : #include "smbd/smbd.h"
      32             : #include "nfs4_acls.h"
      33             : #include "librpc/gen_ndr/ndr_nfs4acl.h"
      34             : #include "nfs4acl_xattr.h"
      35             : #include "nfs4acl_xattr_ndr.h"
      36             : 
      37             : #undef DBGC_CLASS
      38             : #define DBGC_CLASS DBGC_VFS
      39             : 
      40        3756 : static struct nfs4acl *nfs4acl_blob2acl(DATA_BLOB *blob, TALLOC_CTX *mem_ctx)
      41             : {
      42             :         enum ndr_err_code ndr_err;
      43        3756 :         struct nfs4acl *acl = talloc_zero(mem_ctx, struct nfs4acl);
      44             : 
      45        3756 :         if (acl == NULL) {
      46           0 :                 errno = ENOMEM;
      47           0 :                 return NULL;
      48             :         }
      49             : 
      50        3756 :         ndr_err = ndr_pull_struct_blob(blob, acl, acl,
      51             :                 (ndr_pull_flags_fn_t)ndr_pull_nfs4acl);
      52             : 
      53        3756 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
      54           0 :                 DBG_ERR("ndr_pull_acl_t failed: %s\n", ndr_errstr(ndr_err));
      55           0 :                 TALLOC_FREE(acl);
      56           0 :                 return NULL;
      57             :         }
      58        3756 :         return acl;
      59             : }
      60             : 
      61        2142 : static DATA_BLOB nfs4acl_acl2blob(TALLOC_CTX *mem_ctx, struct nfs4acl *acl)
      62             : {
      63             :         enum ndr_err_code ndr_err;
      64             :         DATA_BLOB blob;
      65             : 
      66        2142 :         ndr_err = ndr_push_struct_blob(&blob, mem_ctx, acl,
      67             :                 (ndr_push_flags_fn_t)ndr_push_nfs4acl);
      68             : 
      69        2142 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
      70           0 :                 DBG_ERR("ndr_push_acl_t failed: %s\n", ndr_errstr(ndr_err));
      71           0 :                 return data_blob_null;
      72             :         }
      73        2142 :         return blob;
      74             : }
      75             : 
      76        1252 : static uint16_t nfs4acl_to_smb4acl_flags(uint8_t nfs4acl_flags)
      77             : {
      78        1252 :         uint16_t smb4acl_flags = SEC_DESC_SELF_RELATIVE;
      79             : 
      80        1252 :         if (nfs4acl_flags & ACL4_AUTO_INHERIT) {
      81         148 :                 smb4acl_flags |= SEC_DESC_DACL_AUTO_INHERITED;
      82             :         }
      83        1252 :         if (nfs4acl_flags & ACL4_PROTECTED) {
      84         294 :                 smb4acl_flags |= SEC_DESC_DACL_PROTECTED;
      85             :         }
      86        1252 :         if (nfs4acl_flags & ACL4_DEFAULTED) {
      87           0 :                 smb4acl_flags |= SEC_DESC_DACL_DEFAULTED;
      88             :         }
      89             : 
      90        1252 :         return smb4acl_flags;
      91             : }
      92             : 
      93        3756 : NTSTATUS nfs4acl_ndr_blob_to_smb4(struct vfs_handle_struct *handle,
      94             :                                   TALLOC_CTX *mem_ctx,
      95             :                                   DATA_BLOB *blob,
      96             :                                   struct SMB4ACL_T **_smb4acl)
      97             : {
      98        3756 :         struct nfs4acl *nfs4acl = NULL;
      99        3756 :         struct SMB4ACL_T *smb4acl = NULL;
     100        3756 :         TALLOC_CTX *frame = talloc_stackframe();
     101        3756 :         struct nfs4acl_config *config = NULL;
     102             :         int i;
     103             : 
     104        3756 :         SMB_VFS_HANDLE_GET_DATA(handle, config,
     105             :                                 struct nfs4acl_config,
     106             :                                 return NT_STATUS_INTERNAL_ERROR);
     107             : 
     108        3756 :         nfs4acl = nfs4acl_blob2acl(blob, frame);
     109        3756 :         if (nfs4acl == NULL) {
     110           0 :                 TALLOC_FREE(frame);
     111           0 :                 return NT_STATUS_INTERNAL_ERROR;
     112             :         }
     113             : 
     114        3756 :         smb4acl = smb_create_smb4acl(mem_ctx);
     115        3756 :         if (smb4acl == NULL) {
     116           0 :                 TALLOC_FREE(frame);
     117           0 :                 return NT_STATUS_NO_MEMORY;
     118             :         }
     119             : 
     120        3756 :         if (config->nfs_version > ACL4_XATTR_VERSION_40 &&
     121        1252 :             nfs4acl->a_version > ACL4_XATTR_VERSION_40)
     122             :         {
     123             :                 uint16_t smb4acl_flags;
     124             : 
     125        1252 :                 smb4acl_flags = nfs4acl_to_smb4acl_flags(nfs4acl->a_flags);
     126        1252 :                 smbacl4_set_controlflags(smb4acl, smb4acl_flags);
     127             :         }
     128             : 
     129        8720 :         for (i = 0; i < nfs4acl->a_count; i++) {
     130             :                 SMB_ACE4PROP_T aceprop;
     131             : 
     132        4964 :                 aceprop.aceType  = (uint32_t) nfs4acl->ace[i].e_type;
     133        4964 :                 aceprop.aceFlags = (uint32_t) nfs4acl->ace[i].e_flags;
     134        4964 :                 aceprop.aceMask  = (uint32_t) nfs4acl->ace[i].e_mask;
     135        4964 :                 aceprop.who.id   = (uint32_t) nfs4acl->ace[i].e_id;
     136             : 
     137        4964 :                 if (!strcmp(nfs4acl->ace[i].e_who,
     138             :                             NFS4ACL_XATTR_OWNER_WHO)) {
     139        2914 :                         aceprop.flags = SMB_ACE4_ID_SPECIAL;
     140        2914 :                         aceprop.who.special_id = SMB_ACE4_WHO_OWNER;
     141        2050 :                 } else if (!strcmp(nfs4acl->ace[i].e_who,
     142             :                                    NFS4ACL_XATTR_GROUP_WHO)) {
     143           0 :                         aceprop.flags = SMB_ACE4_ID_SPECIAL;
     144           0 :                         aceprop.who.special_id = SMB_ACE4_WHO_GROUP;
     145        2050 :                 } else if (!strcmp(nfs4acl->ace[i].e_who,
     146             :                                    NFS4ACL_XATTR_EVERYONE_WHO)) {
     147        1368 :                         aceprop.flags = SMB_ACE4_ID_SPECIAL;
     148        1368 :                         aceprop.who.special_id = SMB_ACE4_WHO_EVERYONE;
     149             :                 } else {
     150         682 :                         aceprop.flags = 0;
     151             :                 }
     152             : 
     153        4964 :                 if (smb_add_ace4(smb4acl, &aceprop) == NULL) {
     154           0 :                         TALLOC_FREE(frame);
     155           0 :                         return NT_STATUS_NO_MEMORY;
     156             :                 }
     157             :         }
     158             : 
     159        3756 :         *_smb4acl = smb4acl;
     160        3756 :         TALLOC_FREE(frame);
     161        3756 :         return NT_STATUS_OK;
     162             : }
     163             : 
     164         714 : static uint8_t smb4acl_to_nfs4acl_flags(uint16_t smb4acl_flags)
     165             : {
     166         714 :         uint8_t flags = 0;
     167             : 
     168         714 :         if (smb4acl_flags & SEC_DESC_DACL_AUTO_INHERITED) {
     169         114 :                 flags |= ACL4_AUTO_INHERIT;
     170             :         }
     171         714 :         if (smb4acl_flags & SEC_DESC_DACL_PROTECTED) {
     172         238 :                 flags |= ACL4_PROTECTED;
     173             :         }
     174         714 :         if (smb4acl_flags & SEC_DESC_DACL_DEFAULTED) {
     175           0 :                 flags |= ACL4_DEFAULTED;
     176             :         }
     177             : 
     178         714 :         return flags;
     179             : }
     180             : 
     181        2142 : static bool nfs4acl_smb4acl2nfs4acl(vfs_handle_struct *handle,
     182             :                                     TALLOC_CTX *mem_ctx,
     183             :                                     struct SMB4ACL_T *smbacl,
     184             :                                     struct nfs4acl **_nfs4acl,
     185             :                                     bool denymissingspecial)
     186             : {
     187        2142 :         struct nfs4acl_config *config = NULL;
     188        2142 :         struct nfs4acl *nfs4acl = NULL;
     189        2142 :         struct SMB4ACE_T *smbace = NULL;
     190        2142 :         bool have_special_id = false;
     191             :         int i;
     192             : 
     193        2142 :         SMB_VFS_HANDLE_GET_DATA(handle, config,
     194             :                                 struct nfs4acl_config,
     195             :                                 return false);
     196             : 
     197        2142 :         nfs4acl = talloc_zero(mem_ctx, struct nfs4acl);
     198        2142 :         if (nfs4acl == NULL) {
     199           0 :                 errno = ENOMEM;
     200           0 :                 return false;
     201             :         }
     202             : 
     203        2142 :         nfs4acl->a_count = smb_get_naces(smbacl);
     204             : 
     205        2142 :         nfs4acl->ace = talloc_zero_array(nfs4acl, struct nfs4ace,
     206             :                                          nfs4acl->a_count);
     207        2142 :         if (nfs4acl->ace == NULL) {
     208           0 :                 TALLOC_FREE(nfs4acl);
     209           0 :                 errno = ENOMEM;
     210           0 :                 return false;
     211             :         }
     212             : 
     213        2142 :         nfs4acl->a_version = config->nfs_version;
     214        2142 :         if (nfs4acl->a_version > ACL4_XATTR_VERSION_40) {
     215             :                 uint16_t smb4acl_flags;
     216             :                 uint8_t flags;
     217             : 
     218         714 :                 smb4acl_flags = smbacl4_get_controlflags(smbacl);
     219         714 :                 flags = smb4acl_to_nfs4acl_flags(smb4acl_flags);
     220         714 :                 nfs4acl->a_flags = flags;
     221             :         }
     222             : 
     223        2142 :         for (smbace = smb_first_ace4(smbacl), i = 0;
     224        4516 :              smbace != NULL;
     225        2374 :              smbace = smb_next_ace4(smbace), i++)
     226             :         {
     227        2374 :                 SMB_ACE4PROP_T *aceprop = smb_get_ace4(smbace);
     228             : 
     229        2374 :                 nfs4acl->ace[i].e_type        = aceprop->aceType;
     230        2374 :                 nfs4acl->ace[i].e_flags       = aceprop->aceFlags;
     231        2374 :                 nfs4acl->ace[i].e_mask        = aceprop->aceMask;
     232        2374 :                 nfs4acl->ace[i].e_id          = aceprop->who.id;
     233        2374 :                 if(aceprop->flags & SMB_ACE4_ID_SPECIAL) {
     234        2222 :                         switch(aceprop->who.special_id) {
     235         282 :                         case SMB_ACE4_WHO_EVERYONE:
     236         282 :                                 nfs4acl->ace[i].e_who =
     237             :                                         NFS4ACL_XATTR_EVERYONE_WHO;
     238         282 :                                 break;
     239        1940 :                         case SMB_ACE4_WHO_OWNER:
     240        1940 :                                 nfs4acl->ace[i].e_who =
     241             :                                         NFS4ACL_XATTR_OWNER_WHO;
     242        1940 :                                 break;
     243           0 :                         case SMB_ACE4_WHO_GROUP:
     244           0 :                                 nfs4acl->ace[i].e_who =
     245             :                                         NFS4ACL_XATTR_GROUP_WHO;
     246           0 :                                 break;
     247           0 :                         default:
     248           0 :                                 DBG_DEBUG("unsupported special_id %d\n",
     249             :                                           aceprop->who.special_id);
     250           0 :                                 continue; /* don't add it !!! */
     251             :                         }
     252        2222 :                         have_special_id = true;
     253             :                 } else {
     254         152 :                         nfs4acl->ace[i].e_who = "";
     255             :                 }
     256             :         }
     257             : 
     258        2142 :         if (!have_special_id && denymissingspecial) {
     259           0 :                 TALLOC_FREE(nfs4acl);
     260           0 :                 errno = EACCES;
     261           0 :                 return false;
     262             :         }
     263             : 
     264        2142 :         SMB_ASSERT(i == nfs4acl->a_count);
     265             : 
     266        2142 :         *_nfs4acl = nfs4acl;
     267        2142 :         return true;
     268             : }
     269             : 
     270        2142 : NTSTATUS nfs4acl_smb4acl_to_ndr_blob(vfs_handle_struct *handle,
     271             :                                      TALLOC_CTX *mem_ctx,
     272             :                                      struct SMB4ACL_T *smb4acl,
     273             :                                      DATA_BLOB *_blob)
     274             : {
     275        2142 :         struct nfs4acl *nfs4acl = NULL;
     276             :         DATA_BLOB blob;
     277             :         bool denymissingspecial;
     278             :         bool ok;
     279             : 
     280        2142 :         denymissingspecial = lp_parm_bool(SNUM(handle->conn),
     281             :                                           "nfs4acl_xattr",
     282             :                                           "denymissingspecial", false);
     283             : 
     284        2142 :         ok = nfs4acl_smb4acl2nfs4acl(handle, talloc_tos(), smb4acl, &nfs4acl,
     285             :                                      denymissingspecial);
     286        2142 :         if (!ok) {
     287           0 :                 DBG_ERR("Failed to convert smb ACL to nfs4 ACL.\n");
     288           0 :                 return NT_STATUS_INTERNAL_ERROR;
     289             :         }
     290             : 
     291        2142 :         blob = nfs4acl_acl2blob(mem_ctx, nfs4acl);
     292        2142 :         TALLOC_FREE(nfs4acl);
     293        2142 :         if (blob.data == NULL) {
     294           0 :                 DBG_ERR("Failed to convert ACL to linear blob for xattr\n");
     295           0 :                 return NT_STATUS_INTERNAL_ERROR;
     296             :         }
     297             : 
     298        2142 :         *_blob = blob;
     299        2142 :         return NT_STATUS_OK;
     300             : }

Generated by: LCOV version 1.14