From: JAMES LEWIS NANCE (jlnance@eos.ncsu.edu)
Date: 12/18/92


From: jlnance@eos.ncsu.edu (JAMES LEWIS NANCE)
Subject: ANNOUNCE Normal user floppy file systems
Date: Fri, 18 Dec 1992 20:09:18 GMT


I read some requests last week for information about allowing a normal user to
mount floppys. I have written a program which will do this. I do not think
that it adds any security risk to have it on your system. If anyone can think
of a way to use it to breach security, send me some mail and I will modify the
program to try to make it more secure.

Read the comments for more doccumentation.

Jim Nance

/*
 * This program provides a safe way for normal users to create, mount, and
 * unmount floppy file systems. When the floppy is mounted, this program
 * executes the command chmod -f -R a-s to unset all of the suid/sgid bits.
 * a better way would probably be to mount the floppy with an option to ignore
 * set uid bits, but I don't know how to do this.
 *
 * The executable produced by the program must be owned by root, and have
 * the suid bit set. Ie:
 * gcc -O -s -o floppy floppy.c
 * chown root floppy
 * chmod 4755 floppy
 *
 * If you have a 3.5" drive, you should change the #define FlopBlocks to
 * 2880, or you will have to use the -b2880 flag when you run the program.
 * By default the program mounts the floppy on /tmp/floppy. You can over ride
 * this with the -m flag or you can change #define MntPoint to be something
 * else. If you mount the floppy on a nonexistant mount point, the program
 * will create the mount point, and remove it when you unmount the floppy. If
 * the mount point exists before the program is run, it is not removed by the
 * program when the floppy is unmounted.
 *
 * Summary of commands. Assume the executable is called floppy.
 *
 * floppy format # low level formats the floppy
 * floppy new # high level formats the floppy
 * floppy mount # mounts the floppy
 * floppy unmount # unmounts the floppy
 */

#include "stdlib.h"
#include "string.h"
#include "stdarg.h"
#include "stdio.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "sys/wait.h"
#include "unistd.h"

#define MntPoint "/tmp/floppy"
#define FlopBlocks "2400"
#define Ssiz 256

/*VARARGS1*/
void err_exit(char *fmt, ...) {
va_list args;

va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
fputs("\n", stderr);
exit(1);
}

/*VARARGS1*/
void new_sys(char *fmt, ...) {
char cmd[1024];
va_list args;

va_start(args, fmt);
vsprintf(cmd, fmt, args);
va_end(args);
printf("system: %s\n", cmd);
system(cmd);
}

void print_help(char **argv) {
int i;
static char *cp[] = {
     "\n",
     "options are :\n",
     " -dX -> use device X as the floppy drive. Default is /dev/fd0\n",
     " -eX -> use program X in place of mkfs Default is mkfs -c\n",
     " -bX -> append X to mkfs command Default is ",
     FlopBlocks,
     "\n",
     " -mX -> mount floppy on directory X Default is ",
     MntPoint,
     " \n",
     " \n",
     "cmd is one of:\n",
     " format -> format the floppy\n",
     " new -> create a file system on the floppy\n",
     " mount -> mount the floppy on /tmp/floppy\n",
     " unmount -> unmount the floppy\n",
     NULL};

printf("USAGE: %s {options} cmd", argv[0]);
for(i=0; cp[i]; fputs(cp[i++],stdout));
}

int main(int argc, char **argv, char **envp) {
char dev[Ssiz+1];
char mfs[Ssiz+1];
char blk[Ssiz+1];
char pth[Ssiz+1+20];
char *place;
int i;
int action=0;
uid_t uid = getuid();
gid_t gid = getgid();
pid_t pid;
struct stat buf;

if(setenv("PATH","/bin:/usr/bin:/usr/local/bin:/etc:/usr/ucb", 1))
     err_exit("Can not set PATH environment variable");

strcpy(dev,"/dev/fd0");
strcpy(pth,MntPoint);
strcpy(blk,FlopBlocks);
strcpy(mfs,"mkfs -c");

for(i=1; i<argc; i++) {
     if(!strncmp(argv[i], "-d", 2)) strncpy(dev,argv[i]+2,Ssiz)[Ssiz]='0'; else
     if(!strncmp(argv[i], "-b", 2)) strncpy(blk,argv[i]+2,Ssiz)[Ssiz]='0'; else
     if(!strncmp(argv[i], "-e", 2)) strncpy(mfs,argv[i]+2,Ssiz)[Ssiz]='0'; else
     if(!strncmp(argv[i], "-m", 2)) strncpy(pth,argv[i]+2,Ssiz)[Ssiz]='0'; else
     if(!strcmp(argv[i],"format" )) action=1; else
     if(!strcmp(argv[i],"new" )) action=2; else
     if(!strcmp(argv[i],"mount" )) action=3; else
     if(!strcmp(argv[i],"unmount")) action=4; else
     if(!strcmp(argv[i],"help" )) {print_help(argv); exit(0);}
     }

switch (action) {
     case 1:
          new_sys("fdformat %s", dev);
          break;
     case 2:
          new_sys("%s %s %s",mfs, dev, blk);
          break;
     case 3:
          if(stat(pth, &buf)) if(pid=fork()) wait(pid); else {
               setuid(uid);
               setgid(gid);
               new_sys("mkdir -p %s/floppy.tmp.dir", pth);
               new_sys("chmod 700 %s", pth);
               exit(0);
               }
          if(stat(pth, &buf)) err_exit("Unable to create %s",pth);
          if(buf.st_uid!=uid) err_exit("You do not own %s", pth);
          if(!(buf.st_mode&S_IFDIR)) err_exit("%s is not a directory",pth);
          new_sys("mount %s %s", dev, pth);
          new_sys("chmod -f -R a-s %s", pth);
          chown(pth, uid, gid);
          break;
     case 4:
          if(stat(pth, &buf)) err_exit("can not stat %s", pth);
          if(buf.st_uid!=uid) err_exit("You do not own %s", pth);
          if(!(buf.st_mode&S_IFDIR)) err_exit("%s is not a directory",pth);
          new_sys("umount %s", dev);

          for(place=pth; *place; place++);
          strcpy(place,"/floppy.tmp.dir");
          if(!stat(pth, &buf)) {
               *place='\0';
               new_sys("rm -rf %s", pth);
               }
          else *place='\0';

          break;
     default: print_help(argv);
     }

return 0;
}