1 /* 2 * Copyright (c) 1992, 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software donated to Berkeley by 6 * Jan-Simon Pendry. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37 #ifndef lint 38 char copyright[] = 39 "@(#) Copyright (c) 1992, 1993, 1994\n\ 40 The Regents of the University of California. All rights reserved.\n"; 41 #endif /* not lint */ 42 43 #ifndef lint 44 /*static char sccsid[] = "from: @(#)mount_umap.c 8.3 (Berkeley) 3/27/94";*/ 45 static char *rcsid = "$Id: mount_umap.c,v 1.2 1994/10/31 04:29:39 cgd Exp $"; 46 #endif /* not lint */ 47 48 #include <sys/param.h> 49 #include <sys/mount.h> 50 #include <sys/stat.h> 51 52 #include <miscfs/umapfs/umap.h> 53 54 #include <err.h> 55 #include <stdio.h> 56 #include <stdlib.h> 57 #include <string.h> 58 #include <unistd.h> 59 60 #include "mntopts.h" 61 62 #define ROOTUSER 0 63 /* 64 * This define controls whether any user but the superuser can own and 65 * write mapfiles. If other users can, system security can be gravely 66 * compromised. If this is not a concern, undefine SECURITY. 67 */ 68 #define MAPSECURITY 1 69 70 /* 71 * This routine provides the user interface to mounting a umap layer. 72 * It takes 4 mandatory parameters. The mandatory arguments are the place 73 * where the next lower level is mounted, the place where the umap layer is to 74 * be mounted, the name of the user mapfile, and the name of the group 75 * mapfile. The routine checks the ownerships and permissions on the 76 * mapfiles, then opens and reads them. Then it calls mount(), which 77 * will, in turn, call the umap version of mount. 78 */ 79 80 struct mntopt mopts[] = { 81 MOPT_STDOPTS, 82 { NULL } 83 }; 84 85 void usage __P((void)); 86 87 int 88 main(argc, argv) 89 int argc; 90 char *argv[]; 91 { 92 static char not[] = "; not mounted."; 93 struct stat statbuf; 94 struct umap_args args; 95 FILE *fp, *gfp; 96 long d1, d2; 97 uid_t mapdata[MAPFILEENTRIES][2]; 98 gid_t gmapdata[GMAPFILEENTRIES][2]; 99 int ch, count, gnentries, mntflags, nentries; 100 char *gmapfile, *mapfile, *source, *target, buf[20]; 101 102 mntflags = 0; 103 mapfile = gmapfile = NULL; 104 while ((ch = getopt(argc, argv, "g:o:u:")) != EOF) 105 switch (ch) { 106 case 'g': 107 gmapfile = optarg; 108 break; 109 case 'o': 110 getmntopts(optarg, mopts, &mntflags); 111 break; 112 case 'u': 113 mapfile = optarg; 114 break; 115 case '?': 116 default: 117 usage(); 118 } 119 argc -= optind; 120 argv += optind; 121 122 if (argc != 2 || mapfile == NULL || gmapfile == NULL) 123 usage(); 124 125 source = argv[0]; 126 target = argv[1]; 127 128 /* Read in uid mapping data. */ 129 if ((fp = fopen(mapfile, "r")) == NULL) 130 err(1, "%s%s", mapfile, not); 131 132 #ifdef MAPSECURITY 133 /* 134 * Check that group and other don't have write permissions on 135 * this mapfile, and that the mapfile belongs to root. 136 */ 137 if (fstat(fileno(fp), &statbuf)) 138 err(1, "%s%s", mapfile, not); 139 if (statbuf.st_mode & S_IWGRP || statbuf.st_mode & S_IWOTH) { 140 strmode(statbuf.st_mode, buf); 141 err(1, "%s: improper write permissions (%s)%s", 142 mapfile, buf, not); 143 } 144 if (statbuf.st_uid != ROOTUSER) 145 errx(1, "%s does not belong to root%s", mapfile, not); 146 #endif /* MAPSECURITY */ 147 148 if ((fscanf(fp, "%d\n", &nentries)) != 1) 149 errx(1, "%s: nentries not found%s", mapfile, not); 150 if (nentries > MAPFILEENTRIES) 151 errx(1, 152 "maximum number of entries is %d%s", MAPFILEENTRIES, not); 153 #if 0 154 (void)printf("reading %d entries\n", nentries); 155 #endif 156 for (count = 0; count < nentries; ++count) { 157 if ((fscanf(fp, "%lu %lu\n", &d1, &d2)) != 2) { 158 if (ferror(fp)) 159 err(1, "%s%s", mapfile, not); 160 if (feof(fp)) 161 errx(1, "%s: unexpected end-of-file%s", 162 mapfile, not); 163 errx(1, "%s: illegal format (line %d)%s", 164 mapfile, count + 2, not); 165 } 166 mapdata[count][0] = d1; 167 mapdata[count][1] = d2; 168 #if 0 169 /* Fix a security hole. */ 170 if (mapdata[count][1] == 0) 171 errx(1, "mapping id 0 not permitted (line %d)%s", 172 count + 2, not); 173 #endif 174 } 175 176 /* Read in gid mapping data. */ 177 if ((gfp = fopen(gmapfile, "r")) == NULL) 178 err(1, "%s%s", gmapfile, not); 179 180 #ifdef MAPSECURITY 181 /* 182 * Check that group and other don't have write permissions on 183 * this group mapfile, and that the file belongs to root. 184 */ 185 if (fstat(fileno(gfp), &statbuf)) 186 err(1, "%s%s", gmapfile, not); 187 if (statbuf.st_mode & S_IWGRP || statbuf.st_mode & S_IWOTH) { 188 strmode(statbuf.st_mode, buf); 189 err(1, "%s: improper write permissions (%s)%s", 190 gmapfile, buf, not); 191 } 192 if (statbuf.st_uid != ROOTUSER) 193 errx(1, "%s does not belong to root%s", gmapfile, not); 194 #endif /* MAPSECURITY */ 195 196 if ((fscanf(gfp, "%d\n", &gnentries)) != 1) 197 errx(1, "nentries not found%s", gmapfile, not); 198 if (gnentries > MAPFILEENTRIES) 199 errx(1, 200 "maximum number of entries is %d%s", GMAPFILEENTRIES, not); 201 #if 0 202 (void)printf("reading %d group entries\n", gnentries); 203 #endif 204 205 for (count = 0; count < gnentries; ++count) { 206 if ((fscanf(gfp, "%lu %lu\n", &d1, &d2)) != 2) { 207 if (ferror(gfp)) 208 err(1, "%s%s", gmapfile, not); 209 if (feof(gfp)) 210 errx(1, "%s: unexpected end-of-file%s", 211 gmapfile, not); 212 errx(1, "%s: illegal format (line %d)%s", 213 gmapfile, count + 2, not); 214 } 215 gmapdata[count][0] = d1; 216 gmapdata[count][1] = d2; 217 } 218 219 220 /* Setup mount call args. */ 221 args.target = source; 222 args.nentries = nentries; 223 args.mapdata = mapdata; 224 args.gnentries = gnentries; 225 args.gmapdata = gmapdata; 226 227 if (mount(MOUNT_UMAP, argv[1], mntflags, &args)) 228 err(1, NULL); 229 exit(0); 230 } 231 232 void 233 usage() 234 { 235 (void)fprintf(stderr, 236 "usage: mount_umap [-o options] -u usermap -g groupmap target_fs mount_point\n"); 237 exit(1); 238 } 239