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