LCOV - code coverage report
Current view: top level - source3/modules - nfs4acl_xattr_xdr.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 154 186 82.8 %
Date: 2024-02-28 12:06:22 Functions: 13 13 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) Ralph Boehme 2017
       3             :  *
       4             :  * This program is free software; you can redistribute it and/or modify
       5             :  * it under the terms of the GNU General Public License as published by
       6             :  * the Free Software Foundation; either version 3 of the License, or
       7             :  * (at your option) any later version.
       8             :  *
       9             :  * This program is distributed in the hope that it will be useful,
      10             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12             :  * GNU General Public License for more details.
      13             :  *
      14             :  * You should have received a copy of the GNU General Public License
      15             :  * along with this program; if not, see <http://www.gnu.org/licenses/>.
      16             :  *
      17             :  */
      18             : 
      19             : #include "includes.h"
      20             : #include "smbd/proto.h"
      21             : #include "libcli/security/security_descriptor.h"
      22             : #include "libcli/security/security_token.h"
      23             : #include "nfs4_acls.h"
      24             : #include "nfs4acl_xattr.h"
      25             : 
      26             : #undef DBGC_CLASS
      27             : #define DBGC_CLASS DBGC_VFS
      28             : 
      29             : #ifdef HAVE_RPC_XDR_H
      30             : /* <rpc/xdr.h> uses TRUE and FALSE */
      31             : #ifdef TRUE
      32             : #undef TRUE
      33             : #endif
      34             : 
      35             : #ifdef FALSE
      36             : #undef FALSE
      37             : #endif
      38             : 
      39             : #ifdef HAVE_RPC_TYPES_H
      40             : #include <rpc/types.h>
      41             : #endif
      42             : #include <rpc/xdr.h>
      43             : #include "nfs41acl.h"
      44             : #include "nfs4acl_xattr_xdr.h"
      45             : #include "nfs4acl_xattr_util.h"
      46             : 
      47        5508 : static unsigned nfs4acli_get_naces(nfsacl41i *nacl)
      48             : {
      49        5508 :         return nacl->na41_aces.na41_aces_len;
      50             : }
      51             : 
      52        6936 : static void nfs4acli_set_naces(nfsacl41i *nacl, unsigned naces)
      53             : {
      54        6936 :         nacl->na41_aces.na41_aces_len = naces;
      55        6936 : }
      56             : 
      57        1252 : static unsigned nfs4acli_get_flags(nfsacl41i *nacl)
      58             : {
      59        1252 :         return nacl->na41_flag;
      60             : }
      61             : 
      62         714 : static void nfs4acli_set_flags(nfsacl41i *nacl, unsigned flags)
      63             : {
      64         714 :         nacl->na41_flag = flags;
      65         714 : }
      66             : 
      67        1428 : static size_t nfs4acli_get_xdrblob_size(nfsacl41i *nacl)
      68             : {
      69             :         size_t acl_size;
      70             :         size_t aces_size;
      71        1428 :         unsigned naces = nfs4acli_get_naces(nacl);
      72             : 
      73        1428 :         acl_size = sizeof(aclflag4) + sizeof(unsigned);
      74             : 
      75        1428 :         if (naces > NFS4ACL_XDR_MAX_ACES) {
      76           0 :                 DBG_ERR("Too many ACEs: %u\n", naces);
      77           0 :                 return 0;
      78             :         }
      79             : 
      80        1428 :         aces_size = naces * sizeof(struct nfsace4i);
      81        1428 :         if (acl_size + aces_size < acl_size) {
      82           0 :                 return 0;
      83             :         }
      84        1428 :         acl_size += aces_size;
      85             : 
      86        1428 :         return acl_size;
      87             : }
      88             : 
      89        2504 : static size_t nfs4acli_get_xdrblob_naces(size_t _blobsize)
      90             : {
      91        2504 :         size_t blobsize = _blobsize;
      92             : 
      93        2504 :         blobsize -= sizeof(aclflag4);
      94        2504 :         blobsize -= sizeof(unsigned);
      95        2504 :         if (blobsize > _blobsize) {
      96           0 :                 return 0;
      97             :         }
      98        2504 :         return (blobsize / sizeof(struct nfsace4i));
      99             : }
     100             : 
     101        3932 : static nfsacl41i *nfs4acli_alloc(TALLOC_CTX *mem_ctx, unsigned naces)
     102             : {
     103        3932 :         size_t acl_size = sizeof(nfsacl41i) + (naces * sizeof(struct nfsace4i));
     104        3932 :         nfsacl41i *nacl = NULL;
     105             : 
     106        3932 :         if (naces > NFS4ACL_XDR_MAX_ACES) {
     107           0 :                 DBG_ERR("Too many ACEs: %d\n", naces);
     108           0 :                 return NULL;
     109             :         }
     110             : 
     111        3932 :         nacl = talloc_zero_size(mem_ctx, acl_size);
     112        3932 :         if (nacl == NULL) {
     113           0 :                 DBG_ERR("talloc_zero_size failed\n");
     114           0 :                 return NULL;
     115             :         }
     116             : 
     117        3932 :         nfs4acli_set_naces(nacl, naces);
     118        3932 :         nacl->na41_aces.na41_aces_val =
     119        3932 :                 (nfsace4i *)((char *)nacl + sizeof(nfsacl41i));
     120             : 
     121        3932 :         return nacl;
     122             : }
     123             : 
     124        4848 : static nfsace4i *nfs4acli_get_ace(nfsacl41i *nacl, size_t n)
     125             : {
     126        4848 :         return &nacl->na41_aces.na41_aces_val[n];
     127             : }
     128             : 
     129        1428 : static bool smb4acl_to_nfs4acli(vfs_handle_struct *handle,
     130             :                                 TALLOC_CTX *mem_ctx,
     131             :                                 struct SMB4ACL_T *smb4acl,
     132             :                                 nfsacl41i **_nacl)
     133             : {
     134        1428 :         struct nfs4acl_config *config = NULL;
     135        1428 :         struct SMB4ACE_T *smb4ace = NULL;
     136        1428 :         size_t smb4naces = 0;
     137        1428 :         nfsacl41i *nacl = NULL;
     138        1428 :         uint16_t smb4acl_flags = 0;
     139        1428 :         unsigned nacl_flags = 0;
     140             : 
     141        1428 :         SMB_VFS_HANDLE_GET_DATA(handle, config,
     142             :                                 struct nfs4acl_config,
     143             :                                 return false);
     144             : 
     145        1428 :         smb4naces = smb_get_naces(smb4acl);
     146        1428 :         nacl = nfs4acli_alloc(mem_ctx, smb4naces);
     147        1428 :         nfs4acli_set_naces(nacl, 0);
     148             : 
     149        1428 :         if (config->nfs_version > ACL4_XATTR_VERSION_40) {
     150         714 :                 smb4acl_flags = smbacl4_get_controlflags(smb4acl);
     151         714 :                 nacl_flags = smb4acl_to_nfs4acl_flags(smb4acl_flags);
     152         714 :                 nfs4acli_set_flags(nacl, nacl_flags);
     153             :         }
     154             : 
     155        1428 :         smb4ace = smb_first_ace4(smb4acl);
     156        3004 :         while (smb4ace != NULL) {
     157        1576 :                 SMB_ACE4PROP_T *ace4prop = smb_get_ace4(smb4ace);
     158        1576 :                 size_t nace_count = nfs4acli_get_naces(nacl);
     159        1576 :                 nfsace4i *nace = nfs4acli_get_ace(nacl, nace_count);
     160             : 
     161        1576 :                 nace->type = ace4prop->aceType;
     162        1576 :                 nace->flag = ace4prop->aceFlags;
     163        1576 :                 nace->access_mask = ace4prop->aceMask;
     164             : 
     165        1576 :                 if (ace4prop->flags & SMB_ACE4_ID_SPECIAL) {
     166        1480 :                         nace->iflag |= ACEI4_SPECIAL_WHO;
     167             : 
     168        1480 :                         switch (ace4prop->who.special_id) {
     169        1292 :                         case SMB_ACE4_WHO_OWNER:
     170        1292 :                                 nace->who = ACE4_SPECIAL_OWNER;
     171        1292 :                                 break;
     172             : 
     173           0 :                         case SMB_ACE4_WHO_GROUP:
     174           0 :                                 nace->who = ACE4_SPECIAL_GROUP;
     175           0 :                                 break;
     176             : 
     177         188 :                         case SMB_ACE4_WHO_EVERYONE:
     178         188 :                                 nace->who = ACE4_SPECIAL_EVERYONE;
     179         188 :                                 break;
     180             : 
     181           0 :                         default:
     182           0 :                                 DBG_ERR("Unsupported special id [%d]\n",
     183             :                                         ace4prop->who.special_id);
     184           0 :                                 continue;
     185             :                         }
     186             :                 } else {
     187          96 :                         if (ace4prop->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) {
     188          20 :                                 nace->flag |= ACE4_IDENTIFIER_GROUP;
     189          20 :                                 nace->who = ace4prop->who.gid;
     190             :                         } else {
     191          76 :                                 nace->who = ace4prop->who.uid;
     192             :                         }
     193             :                 }
     194             : 
     195        1576 :                 nace_count++;
     196        1576 :                 nfs4acli_set_naces(nacl, nace_count);
     197        1576 :                 smb4ace = smb_next_ace4(smb4ace);
     198             :         }
     199             : 
     200        1428 :         *_nacl = nacl;
     201        1428 :         return true;
     202             : }
     203             : 
     204        1428 : NTSTATUS nfs4acl_smb4acl_to_xdr_blob(vfs_handle_struct *handle,
     205             :                                      TALLOC_CTX *mem_ctx,
     206             :                                      struct SMB4ACL_T *smb4acl,
     207             :                                      DATA_BLOB *_blob)
     208             : {
     209        1428 :         nfsacl41i *nacl = NULL;
     210        1428 :         XDR xdr = {0};
     211             :         size_t aclblobsize;
     212             :         DATA_BLOB blob;
     213             :         bool ok;
     214             : 
     215        1428 :         ok = smb4acl_to_nfs4acli(handle, talloc_tos(), smb4acl, &nacl);
     216        1428 :         if (!ok) {
     217           0 :                 DBG_ERR("smb4acl_to_nfs4acl failed\n");
     218           0 :                 return NT_STATUS_INTERNAL_ERROR;
     219             :         }
     220             : 
     221        1428 :         aclblobsize = nfs4acli_get_xdrblob_size(nacl);
     222        1428 :         if (aclblobsize == 0) {
     223           0 :                 return NT_STATUS_INTERNAL_ERROR;
     224             :         }
     225             : 
     226        1428 :         blob = data_blob_talloc(mem_ctx, NULL, aclblobsize);
     227        1428 :         if (blob.data == NULL) {
     228           0 :                 TALLOC_FREE(nacl);
     229           0 :                 return NT_STATUS_NO_MEMORY;
     230             :         }
     231             : 
     232        1428 :         xdrmem_create(&xdr, (char *)blob.data, blob.length, XDR_ENCODE);
     233             : 
     234        1428 :         ok = xdr_nfsacl41i(&xdr, nacl);
     235        1428 :         TALLOC_FREE(nacl);
     236        1428 :         if (!ok) {
     237           0 :                 DBG_ERR("xdr_nfs4acl41 failed\n");
     238           0 :                 return NT_STATUS_NO_MEMORY;
     239             :         }
     240             : 
     241        1428 :         *_blob = blob;
     242        1428 :         return NT_STATUS_OK;
     243             : }
     244             : 
     245        2504 : static NTSTATUS nfs4acl_xdr_blob_to_nfs4acli(struct vfs_handle_struct *handle,
     246             :                                              TALLOC_CTX *mem_ctx,
     247             :                                              DATA_BLOB *blob,
     248             :                                              nfsacl41i **_nacl)
     249             : {
     250        2504 :         struct nfs4acl_config *config = NULL;
     251        2504 :         nfsacl41i *nacl = NULL;
     252             :         size_t naces;
     253        2504 :         XDR xdr = {0};
     254             :         bool ok;
     255             : 
     256        2504 :         SMB_VFS_HANDLE_GET_DATA(handle, config,
     257             :                                 struct nfs4acl_config,
     258             :                                 return NT_STATUS_INTERNAL_ERROR);
     259             : 
     260        2504 :         naces = nfs4acli_get_xdrblob_naces(blob->length);
     261        2504 :         nacl = nfs4acli_alloc(mem_ctx, naces);
     262             : 
     263        2504 :         xdrmem_create(&xdr, (char *)blob->data, blob->length, XDR_DECODE);
     264             : 
     265        2504 :         ok = xdr_nfsacl41i(&xdr, nacl);
     266        2504 :         if (!ok) {
     267           0 :                 DBG_ERR("xdr_nfs4acl41 failed\n");
     268           0 :                 return NT_STATUS_INTERNAL_ERROR;
     269             :         }
     270             : 
     271        2504 :         if (config->nfs_version == ACL4_XATTR_VERSION_40) {
     272        1252 :                 nacl->na41_flag = 0;
     273             :         }
     274             : 
     275        2504 :         *_nacl = nacl;
     276        2504 :         return NT_STATUS_OK;
     277             : }
     278             : 
     279        2504 : static NTSTATUS nfs4acli_to_smb4acl(struct vfs_handle_struct *handle,
     280             :                                     TALLOC_CTX *mem_ctx,
     281             :                                     nfsacl41i *nacl,
     282             :                                     struct SMB4ACL_T **_smb4acl)
     283             : {
     284        2504 :         struct nfs4acl_config *config = NULL;
     285        2504 :         struct SMB4ACL_T *smb4acl = NULL;
     286        2504 :         unsigned nfsacl41_flag = 0;
     287        2504 :         uint16_t smb4acl_flags = 0;
     288        2504 :         unsigned naces = nfs4acli_get_naces(nacl);
     289             :         unsigned i;
     290             : 
     291        2504 :         SMB_VFS_HANDLE_GET_DATA(handle, config,
     292             :                                 struct nfs4acl_config,
     293             :                                 return NT_STATUS_INTERNAL_ERROR);
     294             : 
     295        2504 :         smb4acl = smb_create_smb4acl(mem_ctx);
     296        2504 :         if (smb4acl == NULL) {
     297           0 :                 return NT_STATUS_INTERNAL_ERROR;
     298             :         }
     299             : 
     300        2504 :         if (config->nfs_version > ACL4_XATTR_VERSION_40) {
     301        1252 :                 nfsacl41_flag = nfs4acli_get_flags(nacl);
     302        1252 :                 smb4acl_flags = nfs4acl_to_smb4acl_flags(nfsacl41_flag);
     303        1252 :                 smbacl4_set_controlflags(smb4acl, smb4acl_flags);
     304             :         }
     305             : 
     306        2504 :         DBG_DEBUG("flags [%x] nace [%u]\n", smb4acl_flags, naces);
     307             : 
     308        5776 :         for (i = 0; i < naces; i++) {
     309        3272 :                 nfsace4i *nace = nfs4acli_get_ace(nacl, i);
     310        3272 :                 SMB_ACE4PROP_T smbace = { 0 };
     311             : 
     312        3272 :                 DBG_DEBUG("type [%d] iflag [%x] flag [%x] mask [%x] who [%d]\n",
     313             :                           nace->type, nace->iflag, nace->flag,
     314             :                           nace->access_mask, nace->who);
     315             : 
     316        3272 :                 smbace.aceType = nace->type;
     317        3272 :                 smbace.aceFlags = nace->flag;
     318        3272 :                 smbace.aceMask = nace->access_mask;
     319             : 
     320        3272 :                 if (nace->iflag & ACEI4_SPECIAL_WHO) {
     321        2868 :                         smbace.flags |= SMB_ACE4_ID_SPECIAL;
     322             : 
     323        2868 :                         switch (nace->who) {
     324        1956 :                         case ACE4_SPECIAL_OWNER:
     325        1956 :                                 smbace.who.special_id = SMB_ACE4_WHO_OWNER;
     326        1956 :                                 break;
     327             : 
     328           0 :                         case ACE4_SPECIAL_GROUP:
     329           0 :                                 smbace.who.special_id = SMB_ACE4_WHO_GROUP;
     330           0 :                                 break;
     331             : 
     332         912 :                         case ACE4_SPECIAL_EVERYONE:
     333         912 :                                 smbace.who.special_id = SMB_ACE4_WHO_EVERYONE;
     334         912 :                                 break;
     335             : 
     336           0 :                         default:
     337           0 :                                 DBG_ERR("Unknown special id [%d]\n", nace->who);
     338           0 :                                 continue;
     339             :                         }
     340             :                 } else {
     341         404 :                         if (nace->flag & ACE4_IDENTIFIER_GROUP) {
     342          36 :                                 smbace.who.gid = nace->who;
     343             :                         } else {
     344         368 :                                 smbace.who.uid = nace->who;
     345             :                         }
     346             :                 }
     347             : 
     348        3272 :                 smb_add_ace4(smb4acl, &smbace);
     349             :         }
     350             : 
     351        2504 :         *_smb4acl = smb4acl;
     352        2504 :         return NT_STATUS_OK;
     353             : }
     354             : 
     355        2504 : NTSTATUS nfs4acl_xdr_blob_to_smb4(struct vfs_handle_struct *handle,
     356             :                                   TALLOC_CTX *mem_ctx,
     357             :                                   DATA_BLOB *blob,
     358             :                                   struct SMB4ACL_T **_smb4acl)
     359             : {
     360        2504 :         struct nfs4acl_config *config = NULL;
     361        2504 :         nfsacl41i *nacl = NULL;
     362        2504 :         struct SMB4ACL_T *smb4acl = NULL;
     363             :         NTSTATUS status;
     364             : 
     365        2504 :         SMB_VFS_HANDLE_GET_DATA(handle, config,
     366             :                                 struct nfs4acl_config,
     367             :                                 return NT_STATUS_INTERNAL_ERROR);
     368             : 
     369        2504 :         status = nfs4acl_xdr_blob_to_nfs4acli(handle, talloc_tos(), blob, &nacl);
     370        2504 :         if (!NT_STATUS_IS_OK(status)) {
     371           0 :                 return status;
     372             :         }
     373             : 
     374        2504 :         status = nfs4acli_to_smb4acl(handle, mem_ctx, nacl, &smb4acl);
     375        2504 :         TALLOC_FREE(nacl);
     376        2504 :         if (!NT_STATUS_IS_OK(status)) {
     377           0 :                 return status;
     378             :         }
     379             : 
     380        2504 :         *_smb4acl = smb4acl;
     381        2504 :         return NT_STATUS_OK;
     382             : }
     383             : 
     384             : #else /* !HAVE_RPC_XDR_H */
     385             : #include "nfs4acl_xattr_xdr.h"
     386             : NTSTATUS nfs4acl_xdr_blob_to_smb4(struct vfs_handle_struct *handle,
     387             :                                   TALLOC_CTX *mem_ctx,
     388             :                                   DATA_BLOB *blob,
     389             :                                   struct SMB4ACL_T **_smb4acl)
     390             : {
     391             :         return NT_STATUS_NOT_SUPPORTED;
     392             : }
     393             : 
     394             : NTSTATUS nfs4acl_smb4acl_to_xdr_blob(vfs_handle_struct *handle,
     395             :                                      TALLOC_CTX *mem_ctx,
     396             :                                      struct SMB4ACL_T *smbacl,
     397             :                                      DATA_BLOB *blob)
     398             : {
     399             :         return NT_STATUS_NOT_SUPPORTED;
     400             : }
     401             : #endif /* HAVE_RPC_XDR_H */

Generated by: LCOV version 1.14