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