Print this page
NEX-16818 Add fksmbcl development tool
NEX-17264 SMB client test tp_smbutil_013 fails after NEX-14666
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
and: (fix ref leaks)


   4  * The contents of this file are subject to the terms of the
   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 /*
  23  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.

  24  */
  25 
  26 /*
  27  * ACL conversion support for smbfs
  28  * (To/from NT/ZFS-style ACLs.)
  29  */
  30 
  31 #include <sys/types.h>
  32 #include <sys/errno.h>
  33 #include <sys/acl.h>
  34 #include <sys/byteorder.h>
  35 
  36 #ifdef _KERNEL
  37 
  38 #include <sys/cred.h>
  39 #include <sys/cmn_err.h>
  40 #include <sys/kmem.h>
  41 #include <sys/sunddi.h>
  42 #include <sys/vnode.h>
  43 #include <sys/vfs.h>
  44 
  45 #include <sys/kidmap.h>
  46 
  47 #else   /* _KERNEL */
  48 
  49 #include <stdio.h>
  50 #include <stdlib.h>
  51 #include <strings.h>
  52 
  53 #include <idmap.h>
  54 




  55 #endif  /* _KERNEL */
  56 
  57 #include <netsmb/mchain.h>
  58 #include <netsmb/smb.h>
  59 #include "smbfs_ntacl.h"
  60 
  61 #define NT_SD_REVISION  1
  62 #define NT_ACL_REVISION 2
  63 
  64 #ifdef _KERNEL
  65 #define MALLOC(size) kmem_alloc(size, KM_SLEEP)
  66 #define FREESZ(p, sz) kmem_free(p, sz)
  67 #else   /* _KERNEL */
  68 #define MALLOC(size) malloc(size)
  69 /*
  70  * Define FREESZ() as inline function so the compiler will not
  71  * trigger variable set but not used warning for sz in calling function.
  72  */
  73 /* ARGSUSED */
  74 static inline void
  75 FREESZ(void *p, size_t sz __unused)
  76 {
  77         free(p);
  78 }
  79 #endif  /* _KERNEL */
  80 
  81 #define ERRCHK(expr)    if ((error = expr) != 0) goto errout
  82 
  83 /*
  84  * Security IDentifier (SID)


 870         /*
 871          * Fill in the ZFS-style ACE
 872          */
 873         zacep->a_who = zwho;
 874         zacep->a_access_mask = zamask;
 875         zacep->a_flags = zflags;
 876         zacep->a_type = ntace->ace_hdr.ace_type;
 877 }
 878 
 879 /*
 880  * Convert an internal SD to a ZFS-style ACL.
 881  * Note optional args: vsa/acl, uidp, gidp.
 882  *
 883  * This makes two passes over the SD, the first building a
 884  * "batch" request for idmap with results in mapinfo, the
 885  * second building a ZFS-style ACL using the idmap results.
 886  */
 887 int
 888 smbfs_acl_sd2zfs(
 889         i_ntsd_t *sd,
 890 #ifdef  _KERNEL
 891         vsecattr_t *acl_info,
 892 #else /* _KERNEL */
 893         acl_t *acl_info,
 894 #endif /* _KERNEL */
 895         uid_t *uidp, gid_t *gidp)
 896 {
 897         struct mapinfo2uid *mip, *mapinfo = NULL;
 898         int error, i, mapcnt, zacecnt, zacl_size;
 899         ace_t *zacep0, *zacep;
 900         uid_t own_uid = (uid_t)-1;
 901         gid_t own_gid = (gid_t)-1;
 902         i_ntacl_t *ntacl;
 903         i_ntace_t **ntacep;
 904         idmap_get_handle_t *idmap_gh = NULL;
 905         idmap_stat      idms;
 906 
 907         /*
 908          * sanity checks
 909          */
 910         if (acl_info) {
 911 #ifndef _KERNEL
 912                 if (acl_info->acl_type != ACE_T ||
 913                     acl_info->acl_aclp != NULL ||
 914                     acl_info->acl_entry_size != sizeof (ace_t))
 915                         return (EINVAL);
 916 #endif /* _KERNEL */
 917                 if ((sd->sd_flags & SD_DACL_PRESENT) == 0)
 918                         return (EINVAL);
 919         }
 920 
 921         /*
 922          * How many SID mappings will we need?
 923          */
 924         mapcnt = 0;
 925         if (sd->sd_owner)
 926                 mapcnt++;
 927         if (sd->sd_group)
 928                 mapcnt++;
 929         if ((sd->sd_flags & SD_SACL_PRESENT) &&
 930             (sd->sd_sacl != NULL))
 931                 mapcnt += sd->sd_sacl->acl_acecount;
 932         if ((sd->sd_flags & SD_DACL_PRESENT) &&
 933             (sd->sd_dacl != NULL))
 934                 mapcnt += sd->sd_dacl->acl_acecount;
 935         if (mapcnt == 0) {
 936                 /*


1100                  * The SD has a NULL DACL.  That means
1101                  * everyone@, full-control
1102                  */
1103                 zacep->a_who = (uid_t)-1;
1104                 zacep->a_access_mask = ACE_ALL_PERMS;
1105                 zacep->a_flags = ACE_EVERYONE;
1106                 zacep->a_type = ACCESS_ALLOWED_ACE_TYPE;
1107         } else if (sd->sd_dacl->acl_acecount == 0) {
1108                 /*
1109                  * The SD has an Empty DACL.  We need
1110                  * at least one ACE, so add one giving
1111                  * the owner the usual implied access.
1112                  */
1113                 zacep->a_who = (uid_t)-1;
1114                 zacep->a_access_mask = ACE_READ_ATTRIBUTES | \
1115                     ACE_READ_ACL | ACE_WRITE_ACL;
1116                 zacep->a_flags = ACE_OWNER;
1117                 zacep->a_type = ACCESS_ALLOWED_ACE_TYPE;
1118         }
1119 
1120 #ifdef _KERNEL
1121         acl_info->vsa_aclcnt = zacecnt;
1122         acl_info->vsa_aclentp = zacep0;
1123         acl_info->vsa_aclentsz = zacl_size;
1124 #else   /* _KERNEL */
1125         acl_info->acl_cnt = zacecnt;
1126         acl_info->acl_aclp = zacep0;
1127 #endif  /* _KERNEL */
1128 
1129 done:
1130         error = 0;
1131 
1132 errout:
1133         if (mapinfo != NULL)
1134                 FREESZ(mapinfo, mapcnt * sizeof (*mapinfo));
1135 #ifdef  _KERNEL
1136         if (idmap_gh != NULL)
1137                 kidmap_get_destroy(idmap_gh);
1138 #else /* _KERNEL */
1139         if (idmap_gh != NULL)
1140                 idmap_get_destroy(idmap_gh);


1209         bzero(sid, size);
1210 
1211         /* Fill it in. */
1212         sid->sid_revision = 1;
1213         sid->sid_subauthcount = sacnt;
1214         for (i = 5; i >= 0; i--) {
1215                 sid->sid_authority[i] = auth & 0xFF;
1216                 auth = auth >> 8;
1217         }
1218 
1219         err = EINVAL;
1220         if (ridp != NULL)
1221                 sacnt--; /* Last SA not from string */
1222         p = np;
1223         for (i = 0; i < sacnt; i++) {
1224                 if (*p != '-') {
1225                         err = EINVAL;
1226                         goto out;
1227                 }
1228                 p++;
1229 #ifdef  _KERNEL
1230                 err = ddi_strtoul(p, &np, 10, &sa);
1231                 if (err != 0)
1232                         goto out;
1233 #else   /* _KERNEL */
1234                 sa = strtoul(p, &np, 10);
1235                 if (p == np) {
1236                         err = EINVAL;
1237                         goto out;
1238                 }
1239 #endif  /* _KERNEL */
1240                 sid->sid_subauthvec[i] = (uint32_t)sa;
1241                 p = np;
1242         }
1243         if (*p != '\0')
1244                 goto out;
1245         if (ridp != NULL)
1246                 sid->sid_subauthvec[i] = *ridp;
1247         err = 0;
1248 
1249 out:


1392         ntace->ace_v2.ace_rights = rights;
1393         ntace->ace_v2.ace_sid = sid;
1394 
1395         *ntacep = ntace;
1396         return (0);
1397 }
1398 
1399 /*
1400  * Convert a ZFS-style ACL to an internal SD.
1401  * Set owner/group too if selector indicates.
1402  * Always need to pass uid+gid, either the new
1403  * (when setting them) or existing, so that any
1404  * owner@ or group@ ACEs can be translated.
1405  *
1406  * This makes two passes over the ZFS ACL.  The first builds a
1407  * "batch" request for idmap with results in mapinfo, and the
1408  * second builds the NT SD using the idmap SID results.
1409  */
1410 int
1411 smbfs_acl_zfs2sd(
1412 #ifdef  _KERNEL
1413         vsecattr_t *acl_info,
1414 #else /* _KERNEL */
1415         acl_t *acl_info,
1416 #endif /* _KERNEL */
1417         uid_t own_uid,
1418         gid_t own_gid,
1419         uint32_t selector,
1420         i_ntsd_t **sdp)
1421 {
1422         struct mapinfo2sid *mip, *mip_acl, *mapinfo = NULL;
1423         int aclsz, error, i, mapcnt;
1424         int dacl_acecnt = 0;
1425         int sacl_acecnt = 0;
1426         int zacecnt = 0;
1427         ace_t *zacevec = NULL;
1428         ace_t *zacep;
1429         i_ntsd_t *sd = NULL;
1430         i_ntacl_t *acl = NULL;
1431         i_ntace_t **acep = NULL;
1432         idmap_get_handle_t *idmap_gh = NULL;


1438          */
1439         mapcnt = 0;
1440         if (selector & OWNER_SECURITY_INFORMATION) {
1441                 if (own_uid == (uid_t)-1)
1442                         return (EINVAL);
1443                 mapcnt++;
1444         }
1445         if (selector & GROUP_SECURITY_INFORMATION) {
1446                 if (own_gid == (gid_t)-1)
1447                         return (EINVAL);
1448                 mapcnt++;
1449         }
1450         if (selector & (DACL_SECURITY_INFORMATION |
1451             SACL_SECURITY_INFORMATION)) {
1452                 if (acl_info == NULL)
1453                         return (EINVAL);
1454                 if (own_uid == (uid_t)-1)
1455                         return (EINVAL);
1456                 if (own_gid == (gid_t)-1)
1457                         return (EINVAL);
1458 #ifdef  _KERNEL
1459                 if ((acl_info->vsa_mask & VSA_ACE) == 0)
1460                         return (EINVAL);
1461                 zacecnt = acl_info->vsa_aclcnt;
1462                 zacevec = acl_info->vsa_aclentp;
1463 #else   /* _KERNEL */
1464                 if (acl_info->acl_type != ACE_T ||
1465                     acl_info->acl_entry_size != sizeof (ace_t))
1466                         return (EINVAL);
1467                 zacecnt = acl_info->acl_cnt;
1468                 zacevec = acl_info->acl_aclp;
1469 #endif  /* _KERNEL */
1470                 if (zacecnt == 0 || zacevec == NULL)
1471                         return (EINVAL);
1472                 mapcnt += zacecnt;
1473         }
1474         if (mapcnt == 0)
1475                 return (EINVAL);
1476         mapinfo = MALLOC(mapcnt * sizeof (*mapinfo));
1477         if (mapinfo == NULL)
1478                 return (ENOMEM);




   4  * The contents of this file are subject to the terms of the
   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 /*
  23  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
  25  */
  26 
  27 /*
  28  * ACL conversion support for smbfs
  29  * (To/from NT/ZFS-style ACLs.)
  30  */
  31 
  32 #include <sys/types.h>
  33 #include <sys/errno.h>
  34 #include <sys/acl.h>
  35 #include <sys/byteorder.h>
  36 
  37 #if defined(_KERNEL) || defined(_FAKE_KERNEL)
  38 
  39 #include <sys/cred.h>
  40 #include <sys/cmn_err.h>
  41 #include <sys/kmem.h>
  42 #include <sys/sunddi.h>
  43 #include <sys/vnode.h>
  44 #include <sys/vfs.h>
  45 


  46 #else   /* _KERNEL */
  47 
  48 #include <stdio.h>
  49 #include <stdlib.h>
  50 #include <strings.h>
  51 
  52 #endif  /* _KERNEL */
  53 
  54 #ifdef _KERNEL
  55 #include <sys/kidmap.h>
  56 #else   /* _KERNEL */
  57 #include <idmap.h>
  58 #endif  /* _KERNEL */
  59 
  60 #include <netsmb/mchain.h>
  61 #include <netsmb/smb.h>
  62 #include "smbfs_ntacl.h"
  63 
  64 #define NT_SD_REVISION  1
  65 #define NT_ACL_REVISION 2
  66 
  67 #if defined(_KERNEL) || defined(_FAKE_KERNEL)
  68 #define MALLOC(size) kmem_alloc(size, KM_SLEEP)
  69 #define FREESZ(p, sz) kmem_free(p, sz)
  70 #else   /* _KERNEL */
  71 #define MALLOC(size) malloc(size)
  72 /*
  73  * Define FREESZ() as inline function so the compiler will not
  74  * trigger variable set but not used warning for sz in calling function.
  75  */
  76 /* ARGSUSED */
  77 static inline void
  78 FREESZ(void *p, size_t sz __unused)
  79 {
  80         free(p);
  81 }
  82 #endif  /* _KERNEL */
  83 
  84 #define ERRCHK(expr)    if ((error = expr) != 0) goto errout
  85 
  86 /*
  87  * Security IDentifier (SID)


 873         /*
 874          * Fill in the ZFS-style ACE
 875          */
 876         zacep->a_who = zwho;
 877         zacep->a_access_mask = zamask;
 878         zacep->a_flags = zflags;
 879         zacep->a_type = ntace->ace_hdr.ace_type;
 880 }
 881 
 882 /*
 883  * Convert an internal SD to a ZFS-style ACL.
 884  * Note optional args: vsa/acl, uidp, gidp.
 885  *
 886  * This makes two passes over the SD, the first building a
 887  * "batch" request for idmap with results in mapinfo, the
 888  * second building a ZFS-style ACL using the idmap results.
 889  */
 890 int
 891 smbfs_acl_sd2zfs(
 892         i_ntsd_t *sd,
 893 #if defined(_KERNEL) || defined(_FAKE_KERNEL)
 894         vsecattr_t *acl_info,
 895 #else /* _KERNEL */
 896         acl_t *acl_info,
 897 #endif /* _KERNEL */
 898         uid_t *uidp, gid_t *gidp)
 899 {
 900         struct mapinfo2uid *mip, *mapinfo = NULL;
 901         int error, i, mapcnt, zacecnt, zacl_size;
 902         ace_t *zacep0, *zacep;
 903         uid_t own_uid = (uid_t)-1;
 904         gid_t own_gid = (gid_t)-1;
 905         i_ntacl_t *ntacl;
 906         i_ntace_t **ntacep;
 907         idmap_get_handle_t *idmap_gh = NULL;
 908         idmap_stat      idms;
 909 
 910         /*
 911          * sanity checks
 912          */
 913         if (acl_info) {
 914 #if !defined(_KERNEL) && !defined(_FAKE_KERNEL)
 915                 if (acl_info->acl_type != ACE_T ||
 916                     acl_info->acl_aclp != NULL ||
 917                     acl_info->acl_entry_size != sizeof (ace_t))
 918                         return (EINVAL);
 919 #endif /* !_KERNEL */
 920                 if ((sd->sd_flags & SD_DACL_PRESENT) == 0)
 921                         return (EINVAL);
 922         }
 923 
 924         /*
 925          * How many SID mappings will we need?
 926          */
 927         mapcnt = 0;
 928         if (sd->sd_owner)
 929                 mapcnt++;
 930         if (sd->sd_group)
 931                 mapcnt++;
 932         if ((sd->sd_flags & SD_SACL_PRESENT) &&
 933             (sd->sd_sacl != NULL))
 934                 mapcnt += sd->sd_sacl->acl_acecount;
 935         if ((sd->sd_flags & SD_DACL_PRESENT) &&
 936             (sd->sd_dacl != NULL))
 937                 mapcnt += sd->sd_dacl->acl_acecount;
 938         if (mapcnt == 0) {
 939                 /*


1103                  * The SD has a NULL DACL.  That means
1104                  * everyone@, full-control
1105                  */
1106                 zacep->a_who = (uid_t)-1;
1107                 zacep->a_access_mask = ACE_ALL_PERMS;
1108                 zacep->a_flags = ACE_EVERYONE;
1109                 zacep->a_type = ACCESS_ALLOWED_ACE_TYPE;
1110         } else if (sd->sd_dacl->acl_acecount == 0) {
1111                 /*
1112                  * The SD has an Empty DACL.  We need
1113                  * at least one ACE, so add one giving
1114                  * the owner the usual implied access.
1115                  */
1116                 zacep->a_who = (uid_t)-1;
1117                 zacep->a_access_mask = ACE_READ_ATTRIBUTES | \
1118                     ACE_READ_ACL | ACE_WRITE_ACL;
1119                 zacep->a_flags = ACE_OWNER;
1120                 zacep->a_type = ACCESS_ALLOWED_ACE_TYPE;
1121         }
1122 
1123 #if defined(_KERNEL) || defined(_FAKE_KERNEL)
1124         acl_info->vsa_aclcnt = zacecnt;
1125         acl_info->vsa_aclentp = zacep0;
1126         acl_info->vsa_aclentsz = zacl_size;
1127 #else   /* _KERNEL */
1128         acl_info->acl_cnt = zacecnt;
1129         acl_info->acl_aclp = zacep0;
1130 #endif  /* _KERNEL */
1131 
1132 done:
1133         error = 0;
1134 
1135 errout:
1136         if (mapinfo != NULL)
1137                 FREESZ(mapinfo, mapcnt * sizeof (*mapinfo));
1138 #ifdef  _KERNEL
1139         if (idmap_gh != NULL)
1140                 kidmap_get_destroy(idmap_gh);
1141 #else /* _KERNEL */
1142         if (idmap_gh != NULL)
1143                 idmap_get_destroy(idmap_gh);


1212         bzero(sid, size);
1213 
1214         /* Fill it in. */
1215         sid->sid_revision = 1;
1216         sid->sid_subauthcount = sacnt;
1217         for (i = 5; i >= 0; i--) {
1218                 sid->sid_authority[i] = auth & 0xFF;
1219                 auth = auth >> 8;
1220         }
1221 
1222         err = EINVAL;
1223         if (ridp != NULL)
1224                 sacnt--; /* Last SA not from string */
1225         p = np;
1226         for (i = 0; i < sacnt; i++) {
1227                 if (*p != '-') {
1228                         err = EINVAL;
1229                         goto out;
1230                 }
1231                 p++;
1232 #if defined(_KERNEL) || defined(_FAKE_KERNEL)
1233                 err = ddi_strtoul(p, &np, 10, &sa);
1234                 if (err != 0)
1235                         goto out;
1236 #else   /* _KERNEL */
1237                 sa = strtoul(p, &np, 10);
1238                 if (p == np) {
1239                         err = EINVAL;
1240                         goto out;
1241                 }
1242 #endif  /* _KERNEL */
1243                 sid->sid_subauthvec[i] = (uint32_t)sa;
1244                 p = np;
1245         }
1246         if (*p != '\0')
1247                 goto out;
1248         if (ridp != NULL)
1249                 sid->sid_subauthvec[i] = *ridp;
1250         err = 0;
1251 
1252 out:


1395         ntace->ace_v2.ace_rights = rights;
1396         ntace->ace_v2.ace_sid = sid;
1397 
1398         *ntacep = ntace;
1399         return (0);
1400 }
1401 
1402 /*
1403  * Convert a ZFS-style ACL to an internal SD.
1404  * Set owner/group too if selector indicates.
1405  * Always need to pass uid+gid, either the new
1406  * (when setting them) or existing, so that any
1407  * owner@ or group@ ACEs can be translated.
1408  *
1409  * This makes two passes over the ZFS ACL.  The first builds a
1410  * "batch" request for idmap with results in mapinfo, and the
1411  * second builds the NT SD using the idmap SID results.
1412  */
1413 int
1414 smbfs_acl_zfs2sd(
1415 #if defined(_KERNEL) || defined(_FAKE_KERNEL)
1416         vsecattr_t *acl_info,
1417 #else /* _KERNEL */
1418         acl_t *acl_info,
1419 #endif /* _KERNEL */
1420         uid_t own_uid,
1421         gid_t own_gid,
1422         uint32_t selector,
1423         i_ntsd_t **sdp)
1424 {
1425         struct mapinfo2sid *mip, *mip_acl, *mapinfo = NULL;
1426         int aclsz, error, i, mapcnt;
1427         int dacl_acecnt = 0;
1428         int sacl_acecnt = 0;
1429         int zacecnt = 0;
1430         ace_t *zacevec = NULL;
1431         ace_t *zacep;
1432         i_ntsd_t *sd = NULL;
1433         i_ntacl_t *acl = NULL;
1434         i_ntace_t **acep = NULL;
1435         idmap_get_handle_t *idmap_gh = NULL;


1441          */
1442         mapcnt = 0;
1443         if (selector & OWNER_SECURITY_INFORMATION) {
1444                 if (own_uid == (uid_t)-1)
1445                         return (EINVAL);
1446                 mapcnt++;
1447         }
1448         if (selector & GROUP_SECURITY_INFORMATION) {
1449                 if (own_gid == (gid_t)-1)
1450                         return (EINVAL);
1451                 mapcnt++;
1452         }
1453         if (selector & (DACL_SECURITY_INFORMATION |
1454             SACL_SECURITY_INFORMATION)) {
1455                 if (acl_info == NULL)
1456                         return (EINVAL);
1457                 if (own_uid == (uid_t)-1)
1458                         return (EINVAL);
1459                 if (own_gid == (gid_t)-1)
1460                         return (EINVAL);
1461 #if defined(_KERNEL) || defined(_FAKE_KERNEL)
1462                 if ((acl_info->vsa_mask & VSA_ACE) == 0)
1463                         return (EINVAL);
1464                 zacecnt = acl_info->vsa_aclcnt;
1465                 zacevec = acl_info->vsa_aclentp;
1466 #else   /* _KERNEL */
1467                 if (acl_info->acl_type != ACE_T ||
1468                     acl_info->acl_entry_size != sizeof (ace_t))
1469                         return (EINVAL);
1470                 zacecnt = acl_info->acl_cnt;
1471                 zacevec = acl_info->acl_aclp;
1472 #endif  /* _KERNEL */
1473                 if (zacecnt == 0 || zacevec == NULL)
1474                         return (EINVAL);
1475                 mapcnt += zacecnt;
1476         }
1477         if (mapcnt == 0)
1478                 return (EINVAL);
1479         mapinfo = MALLOC(mapcnt * sizeof (*mapinfo));
1480         if (mapinfo == NULL)
1481                 return (ENOMEM);