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);
|