xref: /titanic_51/usr/src/cmd/fs.d/smbclnt/chacl/chacl.c (revision bd7c6f51f14365fc31d408903b38c02177384d3d)
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
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
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
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