1bd7c6f51SGordon Ross /*
2bd7c6f51SGordon Ross * CDDL HEADER START
3bd7c6f51SGordon Ross *
4bd7c6f51SGordon Ross * The contents of this file are subject to the terms of the
5bd7c6f51SGordon Ross * Common Development and Distribution License (the "License").
6bd7c6f51SGordon Ross * You may not use this file except in compliance with the License.
7bd7c6f51SGordon Ross *
8bd7c6f51SGordon Ross * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9bd7c6f51SGordon Ross * or http://www.opensolaris.org/os/licensing.
10bd7c6f51SGordon Ross * See the License for the specific language governing permissions
11bd7c6f51SGordon Ross * and limitations under the License.
12bd7c6f51SGordon Ross *
13bd7c6f51SGordon Ross * When distributing Covered Code, include this CDDL HEADER in each
14bd7c6f51SGordon Ross * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15bd7c6f51SGordon Ross * If applicable, add the following below this CDDL HEADER, with the
16bd7c6f51SGordon Ross * fields enclosed by brackets "[]" replaced with your own identifying
17bd7c6f51SGordon Ross * information: Portions Copyright [yyyy] [name of copyright owner]
18bd7c6f51SGordon Ross *
19bd7c6f51SGordon Ross * CDDL HEADER END
20bd7c6f51SGordon Ross */
21bd7c6f51SGordon Ross
22bd7c6f51SGordon Ross /*
23bd7c6f51SGordon Ross * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24bd7c6f51SGordon Ross * Use is subject to license terms.
25bd7c6f51SGordon Ross */
26bd7c6f51SGordon Ross
27*6a1a5bb9SJohn Levon /*
28*6a1a5bb9SJohn Levon * Copyright (c) 2018, Joyent, Inc.
29*6a1a5bb9SJohn Levon */
30*6a1a5bb9SJohn Levon
31bd7c6f51SGordon Ross /*
32bd7c6f51SGordon Ross * This is the smbfs/chacl command.
33bd7c6f51SGordon Ross * (just for testing - not installed)
34bd7c6f51SGordon Ross *
35bd7c6f51SGordon Ross * Works like chmod(1), but only supporting A=... forms.
36bd7c6f51SGordon Ross * i.e. chacl A=everyone@:full_set:fd:allow /mnt/foo
37bd7c6f51SGordon Ross *
38bd7c6f51SGordon Ross * Some more test cases:
39bd7c6f51SGordon Ross * /usr/lib/fs/smbfs/chacl -v
40bd7c6f51SGordon Ross * A=user:2147483649:rwxpdDaARWcCos::allow,
41bd7c6f51SGordon Ross * user:2147483653:raRcs::allow,
42bd7c6f51SGordon Ross * everyone@:raRcs::allow
43bd7c6f51SGordon Ross */
44bd7c6f51SGordon Ross
45bd7c6f51SGordon Ross #include <sys/types.h>
46bd7c6f51SGordon Ross #include <sys/errno.h>
47bd7c6f51SGordon Ross #include <sys/stat.h>
48bd7c6f51SGordon Ross #include <sys/acl.h>
49bd7c6f51SGordon Ross #include <sys/acl_impl.h>
50bd7c6f51SGordon Ross
51bd7c6f51SGordon Ross #include <fcntl.h>
52bd7c6f51SGordon Ross #include <stdio.h>
53bd7c6f51SGordon Ross #include <stdlib.h>
54bd7c6f51SGordon Ross #include <unistd.h>
55bd7c6f51SGordon Ross #include <string.h>
56bd7c6f51SGordon Ross #include <aclutils.h>
57bd7c6f51SGordon Ross
58bd7c6f51SGordon Ross #include <netsmb/smbfs_acl.h>
59bd7c6f51SGordon Ross
60bd7c6f51SGordon Ross char *progname;
61bd7c6f51SGordon Ross int Vflag;
62bd7c6f51SGordon Ross
63bd7c6f51SGordon Ross void chacl(char *, uint32_t, uid_t, gid_t, acl_t *);
64bd7c6f51SGordon Ross
65bd7c6f51SGordon Ross static const char Usage[] =
66bd7c6f51SGordon Ross "Usage: %s [-v] [-u UID] [-g GID] A=ACL... file ...\n"
67bd7c6f51SGordon Ross "\twhere A=ACL is like chmod(1)\n";
68bd7c6f51SGordon Ross
69bd7c6f51SGordon Ross void
usage(void)70bd7c6f51SGordon Ross usage(void)
71bd7c6f51SGordon Ross {
72bd7c6f51SGordon Ross fprintf(stderr, Usage, progname);
73bd7c6f51SGordon Ross exit(1);
74bd7c6f51SGordon Ross }
75bd7c6f51SGordon Ross
76bd7c6f51SGordon Ross int
main(int argc,char ** argv)77bd7c6f51SGordon Ross main(int argc, char **argv)
78bd7c6f51SGordon Ross {
79bd7c6f51SGordon Ross uid_t uid = (uid_t)-1;
80bd7c6f51SGordon Ross gid_t gid = (gid_t)-1;
81bd7c6f51SGordon Ross acl_t *acl = NULL;
82bd7c6f51SGordon Ross char *acl_arg;
83bd7c6f51SGordon Ross ulong_t tl;
84bd7c6f51SGordon Ross int c, error;
85bd7c6f51SGordon Ross uint32_t selector;
86bd7c6f51SGordon Ross
87bd7c6f51SGordon Ross progname = argv[0];
88bd7c6f51SGordon Ross
89bd7c6f51SGordon Ross while ((c = getopt(argc, argv, "vu:g:")) != -1) {
90bd7c6f51SGordon Ross switch (c) {
91bd7c6f51SGordon Ross case 'v':
92bd7c6f51SGordon Ross Vflag++;
93bd7c6f51SGordon Ross break;
94bd7c6f51SGordon Ross case 'u':
95bd7c6f51SGordon Ross tl = strtoul(optarg, NULL, 10);
96bd7c6f51SGordon Ross if (tl == 0)
97bd7c6f51SGordon Ross goto badopt;
98bd7c6f51SGordon Ross uid = (uid_t)tl;
99bd7c6f51SGordon Ross break;
100bd7c6f51SGordon Ross case 'g':
101bd7c6f51SGordon Ross tl = strtoul(optarg, NULL, 10);
102bd7c6f51SGordon Ross if (tl == 0)
103bd7c6f51SGordon Ross goto badopt;
104bd7c6f51SGordon Ross gid = (gid_t)tl;
105bd7c6f51SGordon Ross break;
106bd7c6f51SGordon Ross case ':':
107bd7c6f51SGordon Ross fprintf(stderr, "%s: option %c requires arg\n",
108bd7c6f51SGordon Ross progname, c);
109bd7c6f51SGordon Ross usage();
110bd7c6f51SGordon Ross break;
111bd7c6f51SGordon Ross
112bd7c6f51SGordon Ross badopt:
113bd7c6f51SGordon Ross default:
114bd7c6f51SGordon Ross fprintf(stderr, "%s: bad option: %c\n",
115bd7c6f51SGordon Ross progname, c);
116bd7c6f51SGordon Ross usage();
117bd7c6f51SGordon Ross break;
118bd7c6f51SGordon Ross }
119bd7c6f51SGordon Ross }
120bd7c6f51SGordon Ross
121bd7c6f51SGordon Ross if (optind + 1 > argc)
122bd7c6f51SGordon Ross usage();
123bd7c6f51SGordon Ross acl_arg = argv[optind++];
124bd7c6f51SGordon Ross
125bd7c6f51SGordon Ross /*
126bd7c6f51SGordon Ross * Ask libsec to parse the ACL arg.
127bd7c6f51SGordon Ross */
128bd7c6f51SGordon Ross if (strncmp(acl_arg, "A=", 2) != 0)
129bd7c6f51SGordon Ross usage();
130bd7c6f51SGordon Ross error = acl_parse(acl_arg + 2, &acl);
131bd7c6f51SGordon Ross if (error) {
132bd7c6f51SGordon Ross fprintf(stderr, "%s: can not parse ACL: %s\n",
133bd7c6f51SGordon Ross progname, acl_arg);
134bd7c6f51SGordon Ross exit(1);
135bd7c6f51SGordon Ross }
136bd7c6f51SGordon Ross if (acl->acl_type != ACE_T) {
137bd7c6f51SGordon Ross fprintf(stderr, "%s: ACL not ACE_T type: %s\n",
138bd7c6f51SGordon Ross progname, acl_arg);
139bd7c6f51SGordon Ross exit(1);
140bd7c6f51SGordon Ross }
141bd7c6f51SGordon Ross
142bd7c6f51SGordon Ross /*
143bd7c6f51SGordon Ross * Which parts of the SD are being modified?
144bd7c6f51SGordon Ross */
145*6a1a5bb9SJohn Levon selector = DACL_SECURITY_INFORMATION;
146*6a1a5bb9SJohn Levon
147bd7c6f51SGordon Ross if (uid != (uid_t)-1)
148bd7c6f51SGordon Ross selector |= OWNER_SECURITY_INFORMATION;
149bd7c6f51SGordon Ross if (gid != (gid_t)-1)
150bd7c6f51SGordon Ross selector |= GROUP_SECURITY_INFORMATION;
151bd7c6f51SGordon Ross
152bd7c6f51SGordon Ross if (optind == argc)
153bd7c6f51SGordon Ross usage();
154bd7c6f51SGordon Ross for (; optind < argc; optind++)
155bd7c6f51SGordon Ross chacl(argv[optind], selector, uid, gid, acl);
156bd7c6f51SGordon Ross
157bd7c6f51SGordon Ross done:
158bd7c6f51SGordon Ross acl_free(acl);
159bd7c6f51SGordon Ross return (0);
160bd7c6f51SGordon Ross }
161bd7c6f51SGordon Ross
162bd7c6f51SGordon Ross void
chacl(char * file,uint32_t selector,uid_t uid,gid_t gid,acl_t * acl)163bd7c6f51SGordon Ross chacl(char *file, uint32_t selector, uid_t uid, gid_t gid, acl_t *acl)
164bd7c6f51SGordon Ross {
165bd7c6f51SGordon Ross struct stat st;
166bd7c6f51SGordon Ross struct i_ntsd *sd = NULL;
167bd7c6f51SGordon Ross int error, fd;
168bd7c6f51SGordon Ross
169bd7c6f51SGordon Ross /*
170bd7c6f51SGordon Ross * OK, try setting the ACL (via ioctl). Open
171bd7c6f51SGordon Ross * read-only because we're NOT writing data.
172bd7c6f51SGordon Ross * The driver will re-open with the necessary
173bd7c6f51SGordon Ross * access rights to set the ACL.
174bd7c6f51SGordon Ross */
175bd7c6f51SGordon Ross fd = open(file, O_RDONLY, 0);
176bd7c6f51SGordon Ross if (fd < 0) {
177bd7c6f51SGordon Ross perror(file);
178bd7c6f51SGordon Ross exit(1);
179bd7c6f51SGordon Ross }
180bd7c6f51SGordon Ross
181bd7c6f51SGordon Ross if (uid == (uid_t)-1 || gid == (gid_t)-1) {
182bd7c6f51SGordon Ross /*
183bd7c6f51SGordon Ross * If not setting owner or group, we need the
184bd7c6f51SGordon Ross * current owner and group for translating
185bd7c6f51SGordon Ross * references via owner@ or group@ ACEs.
186bd7c6f51SGordon Ross */
187bd7c6f51SGordon Ross if (fstat(fd, &st) != 0) {
188bd7c6f51SGordon Ross perror(file);
189bd7c6f51SGordon Ross exit(1);
190bd7c6f51SGordon Ross }
191bd7c6f51SGordon Ross if (uid == (uid_t)-1)
192bd7c6f51SGordon Ross uid = st.st_uid;
193bd7c6f51SGordon Ross if (gid == (gid_t)-1)
194bd7c6f51SGordon Ross gid = st.st_gid;
195bd7c6f51SGordon Ross }
196bd7c6f51SGordon Ross
197bd7c6f51SGordon Ross /*
198bd7c6f51SGordon Ross * Convert the ZFS ACL to an NT SD.
199bd7c6f51SGordon Ross */
200bd7c6f51SGordon Ross error = smbfs_acl_zfs2sd(acl, uid, gid, selector, &sd);
201bd7c6f51SGordon Ross if (error) {
202bd7c6f51SGordon Ross fprintf(stderr, "%s: failed to convert ACL\n", progname);
203bd7c6f51SGordon Ross exit(1);
204bd7c6f51SGordon Ross }
205bd7c6f51SGordon Ross
206bd7c6f51SGordon Ross if (Vflag) {
207bd7c6f51SGordon Ross
208bd7c6f51SGordon Ross /*
209bd7c6f51SGordon Ross * Print the SD in ZFS form.
210bd7c6f51SGordon Ross */
211bd7c6f51SGordon Ross printf("Solaris security data:\n");
212bd7c6f51SGordon Ross if (uid == (uid_t)-1)
213bd7c6f51SGordon Ross printf("owner: -1\n");
214bd7c6f51SGordon Ross else
215bd7c6f51SGordon Ross printf("owner: %u\n", uid);
216bd7c6f51SGordon Ross if (gid == (gid_t)-1)
217bd7c6f51SGordon Ross printf("group: -1\n");
218bd7c6f51SGordon Ross else
219bd7c6f51SGordon Ross printf("group: %u\n", gid);
220bd7c6f51SGordon Ross acl_printacl(acl, 80, 1);
221bd7c6f51SGordon Ross printf("\n");
222bd7c6f51SGordon Ross
223bd7c6f51SGordon Ross /*
224bd7c6f51SGordon Ross * Print the SD in Windows form.
225bd7c6f51SGordon Ross */
226bd7c6f51SGordon Ross printf("CIFS security data:\n");
227bd7c6f51SGordon Ross smbfs_acl_print_sd(stdout, sd);
228bd7c6f51SGordon Ross printf("\n");
229bd7c6f51SGordon Ross }
230bd7c6f51SGordon Ross
231bd7c6f51SGordon Ross error = smbfs_acl_setsd(fd, selector, sd);
232bd7c6f51SGordon Ross (void) close(fd);
233bd7c6f51SGordon Ross
234bd7c6f51SGordon Ross if (error) {
235bd7c6f51SGordon Ross fprintf(stderr, "%s: ACL set failed, %s\n",
236bd7c6f51SGordon Ross file, strerror(error));
237bd7c6f51SGordon Ross exit(1);
238bd7c6f51SGordon Ross }
239bd7c6f51SGordon Ross
240bd7c6f51SGordon Ross smbfs_acl_free_sd(sd);
241bd7c6f51SGordon Ross }
242