4.4BSD/usr/src/sbin/mount_umap/mount_umap.c
/*
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
* All rights reserved.
*
* This code is derived from software donated to Berkeley by
* Jan-Simon Pendry.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)mount_umap.c 8.1 (Berkeley) 6/5/93
*/
#include <sys/param.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <miscfs/umapfs/umap.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
void usage __P((void));
#define ROOTUSER 0
/* This define controls whether any user but the superuser can own and
* write mapfiles. If other users can, system security can be gravely
* compromised. If this is not a concern, undefine SECURITY.
*/
#define MAPSECURITY 1
/* This routine provides the user interface to mounting a umap layer.
* It takes 4 mandatory parameters. The mandatory arguments are the place
* where the next lower level is mounted, the place where the umap layer is to
* be mounted, the name of the user mapfile, and the name of the group
* mapfile. The routine checks the ownerships and permissions on the
* mapfiles, then opens and reads them. Then it calls mount(), which
* will, in turn, call the umap version of mount.
*/
int
main(argc, argv)
int argc;
char *argv[];
{
int ch, mntflags;
int e, i, nentries, gnentries, count;
int mapdata[MAPFILEENTRIES][2];
int gmapdata[GMAPFILEENTRIES][2];
char *fs_type="umap";
char *source, *target;
char *mapfile, *gmapfile;
FILE *fp, *gfp, *fopen();
struct stat statbuf;
struct umap_args args;
mntflags = 0;
while ((ch = getopt(argc, argv, "F:")) != EOF)
switch(ch) {
case 'F':
mntflags = atoi(optarg);
break;
case '?':
default:
usage();
}
argc -= optind;
argv += optind;
if (argc != 4)
usage();
source = argv[i++];
target = argv[i++];
mapfile = argv[i++];
gmapfile = argv[i++];
#ifdef MAPSECURITY
/*
* Check that group and other don't have write permissions on
* this mapfile, and that the mapfile belongs to root.
*/
if ( stat(mapfile, &statbuf) )
{
printf("mount_umap: can't stat %s\n",mapfile);
perror("mount_umap: error status");
notMounted();
}
if (statbuf.st_mode & S_IWGRP || statbuf.st_mode & S_IWOTH)
{
printf("mount_umap: Improper write permissions for %s, mode %x\n",
mapfile, statbuf.st_mode);
notMounted();
}
if ( statbuf.st_uid != ROOTUSER )
{
printf("mount_umap: %s does not belong to root\n", mapfile);
notMounted();
}
#endif MAPSECURITY
/*
* Read in uid mapping data.
*/
if ((fp = fopen(mapfile, "r")) == NULL) {
printf("mount_umap: can't open %s\n",mapfile);
notMounted();
}
fscanf(fp, "%d\n", &nentries);
if (nentries > MAPFILEENTRIES)
printf("mount_umap: nentries exceeds maximum\n");
#if 0
else
printf("reading %d entries\n", nentries);
#endif
for(count = 0; count<nentries;count++) {
if ((fscanf(fp, "%d %d\n", &(mapdata[count][0]),
&(mapdata[count][1]))) == EOF) {
printf("mount_umap: %s, premature eof\n",mapfile);
notMounted();
}
#if 0
/* fix a security hole */
if (mapdata[count][1] == 0) {
printf("mount_umap: Mapping to UID 0 not allowed\n");
notMounted();
}
#endif
}
/*
* Check that group and other don't have write permissions on
* this group mapfile, and that the file belongs to root.
*/
if ( stat(gmapfile, &statbuf) )
{
printf("mount_umap: can't stat %s\n",gmapfile);
perror("mount_umap: error status");
notMounted();
}
if (statbuf.st_mode & S_IWGRP || statbuf.st_mode & S_IWOTH)
{
printf("mount_umap: Improper write permissions for %s, mode %x\n",
gmapfile, statbuf.st_mode);
}
if ( statbuf.st_uid != ROOTUSER )
{
printf("mount_umap: %s does not belong to root\n", mapfile);
}
/*
* Read in gid mapping data.
*/
if ((gfp = fopen(gmapfile, "r")) == NULL) {
printf("mount_umap: can't open %s\n",gmapfile);
notMounted();
}
fscanf(gfp, "%d\n", &gnentries);
if (gnentries > GMAPFILEENTRIES)
printf("mount_umap: gnentries exceeds maximum\n");
#if 0
else
printf("reading %d group entries\n", gnentries);
#endif
for(count = 0; count<gnentries;count++) {
if ((fscanf(gfp, "%d %d\n", &(gmapdata[count][0]),
&(gmapdata[count][1]))) == EOF) {
printf("mount_umap: %s, premature eof on group mapfile\n",
gmapfile);
notMounted();
}
}
/*
* Setup mount call args.
*/
args.target = source;
args.nentries = nentries;
args.mapdata = &(mapdata[0][0]);
args.gnentries = gnentries;
args.gmapdata = &(gmapdata[0][0]);
#if 0
printf("calling mount_umap(%s,%d,<%s>)\n",target,mntflags,
args.target);
#endif
if (mount(MOUNT_UMAP, argv[1], mntflags, &args)) {
(void)fprintf(stderr, "mount_umap: %s\n", strerror(errno));
}
exit(0);
}
void
usage()
{
(void)fprintf(stderr,
"usage: mount_umap [ -F fsoptions ] target_fs mount_point user_mapfile group_mapfile\n");
exit(1);
}
int
notMounted()
{
(void)fprintf(stderr, "file system not mounted\n");
}