xref: /original-bsd/sbin/mount_umap/mount_umap.c (revision f4a18198)
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  * %sccs.include.redist.c%
9  */
10 
11 #ifndef lint
12 char copyright[] =
13 "@(#) Copyright (c) 1992, 1993, 1994\n\
14 	The Regents of the University of California.  All rights reserved.\n";
15 #endif /* not lint */
16 
17 #ifndef lint
18 static char sccsid[] = "@(#)mount_umap.c	8.4 (Berkeley) 06/14/94";
19 #endif /* not lint */
20 
21 #include <sys/param.h>
22 #include <sys/mount.h>
23 #include <sys/stat.h>
24 
25 #include <miscfs/umapfs/umap.h>
26 
27 #include <err.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <unistd.h>
32 
33 #include "mntopts.h"
34 
35 #define ROOTUSER 0
36 /*
37  * This define controls whether any user but the superuser can own and
38  * write mapfiles.  If other users can, system security can be gravely
39  * compromised.  If this is not a concern, undefine SECURITY.
40  */
41 #define MAPSECURITY 1
42 
43 /*
44  * This routine provides the user interface to mounting a umap layer.
45  * It takes 4 mandatory parameters.  The mandatory arguments are the place
46  * where the next lower level is mounted, the place where the umap layer is to
47  * be mounted, the name of the user mapfile, and the name of the group
48  * mapfile.  The routine checks the ownerships and permissions on the
49  * mapfiles, then opens and reads them.  Then it calls mount(), which
50  * will, in turn, call the umap version of mount.
51  */
52 
53 struct mntopt mopts[] = {
54 	MOPT_STDOPTS,
55 	{ NULL }
56 };
57 
58 void	usage __P((void));
59 
60 int
61 main(argc, argv)
62 	int argc;
63 	char *argv[];
64 {
65 	static char not[] = "; not mounted.";
66 	struct stat statbuf;
67 	struct umap_args args;
68         FILE *fp, *gfp;
69         u_long gmapdata[GMAPFILEENTRIES][2], mapdata[MAPFILEENTRIES][2];
70 	int ch, count, gnentries, mntflags, nentries;
71 	char *gmapfile, *mapfile, *source, *target, buf[20];
72 
73 	mntflags = 0;
74 	mapfile = gmapfile = NULL;
75 	while ((ch = getopt(argc, argv, "g:o:u:")) != EOF)
76 		switch (ch) {
77 		case 'g':
78 			gmapfile = optarg;
79 			break;
80 		case 'o':
81 			getmntopts(optarg, mopts, &mntflags);
82 			break;
83 		case 'u':
84 			mapfile = optarg;
85 			break;
86 		case '?':
87 		default:
88 			usage();
89 		}
90 	argc -= optind;
91 	argv += optind;
92 
93 	if (argc != 2 || mapfile == NULL || gmapfile == NULL)
94 		usage();
95 
96 	source = argv[0];
97 	target = argv[1];
98 
99 	/* Read in uid mapping data. */
100 	if ((fp = fopen(mapfile, "r")) == NULL)
101 		err(1, "%s%s", mapfile, not);
102 
103 #ifdef MAPSECURITY
104 	/*
105 	 * Check that group and other don't have write permissions on
106 	 * this mapfile, and that the mapfile belongs to root.
107 	 */
108 	if (fstat(fileno(fp), &statbuf))
109 		err(1, "%s%s", mapfile, not);
110 	if (statbuf.st_mode & S_IWGRP || statbuf.st_mode & S_IWOTH) {
111 		strmode(statbuf.st_mode, buf);
112 		err(1, "%s: improper write permissions (%s)%s",
113 		    mapfile, buf, not);
114 	}
115 	if (statbuf.st_uid != ROOTUSER)
116 		errx(1, "%s does not belong to root%s", mapfile, not);
117 #endif /* MAPSECURITY */
118 
119 	if ((fscanf(fp, "%d\n", &nentries)) != 1)
120 		errx(1, "%s: nentries not found%s", mapfile, not);
121 	if (nentries > MAPFILEENTRIES)
122 		errx(1,
123 		    "maximum number of entries is %d%s", MAPFILEENTRIES, not);
124 #if 0
125 	(void)printf("reading %d entries\n", nentries);
126 #endif
127 	for (count = 0; count < nentries; ++count) {
128 		if ((fscanf(fp, "%lu %lu\n",
129 		    &(mapdata[count][0]), &(mapdata[count][1]))) != 2) {
130 			if (ferror(fp))
131 				err(1, "%s%s", mapfile, not);
132 			if (feof(fp))
133 				errx(1, "%s: unexpected end-of-file%s",
134 				    mapfile, not);
135 			errx(1, "%s: illegal format (line %d)%s",
136 			    mapfile, count + 2, not);
137 		}
138 #if 0
139 		/* Fix a security hole. */
140 		if (mapdata[count][1] == 0)
141 			errx(1, "mapping id 0 not permitted (line %d)%s",
142 			    count + 2, not);
143 #endif
144 	}
145 
146 	/* Read in gid mapping data. */
147 	if ((gfp = fopen(gmapfile, "r")) == NULL)
148 		err(1, "%s%s", gmapfile, not);
149 
150 #ifdef MAPSECURITY
151 	/*
152 	 * Check that group and other don't have write permissions on
153 	 * this group mapfile, and that the file belongs to root.
154 	 */
155 	if (fstat(fileno(gfp), &statbuf))
156 		err(1, "%s%s", gmapfile, not);
157 	if (statbuf.st_mode & S_IWGRP || statbuf.st_mode & S_IWOTH) {
158 		strmode(statbuf.st_mode, buf);
159 		err(1, "%s: improper write permissions (%s)%s",
160 		    gmapfile, buf, not);
161 	}
162 	if (statbuf.st_uid != ROOTUSER)
163 		errx(1, "%s does not belong to root%s", gmapfile, not);
164 #endif /* MAPSECURITY */
165 
166 	if ((fscanf(gfp, "%d\n", &gnentries)) != 1)
167 		errx(1, "nentries not found%s", gmapfile, not);
168 	if (gnentries > MAPFILEENTRIES)
169 		errx(1,
170 		    "maximum number of entries is %d%s", GMAPFILEENTRIES, not);
171 #if 0
172 	(void)printf("reading %d group entries\n", gnentries);
173 #endif
174 
175 	for (count = 0; count < gnentries; ++count)
176 		if ((fscanf(gfp, "%lu %lu\n",
177 		    &(gmapdata[count][0]), &(gmapdata[count][1]))) != 2) {
178 			if (ferror(gfp))
179 				err(1, "%s%s", gmapfile, not);
180 			if (feof(gfp))
181 				errx(1, "%s: unexpected end-of-file%s",
182 				    gmapfile, not);
183 			errx(1, "%s: illegal format (line %d)%s",
184 			    gmapfile, count + 2, not);
185 		}
186 
187 
188 	/* Setup mount call args. */
189 	args.target = source;
190 	args.nentries = nentries;
191 	args.mapdata = mapdata;
192 	args.gnentries = gnentries;
193 	args.gmapdata = gmapdata;
194 
195 	if (mount(MOUNT_UMAP, argv[1], mntflags, &args))
196 		err(1, NULL);
197 	exit(0);
198 }
199 
200 void
201 usage()
202 {
203 	(void)fprintf(stderr,
204 "usage: mount_umap [-o options] -u usermap -g groupmap target_fs mount_point\n");
205 	exit(1);
206 }
207