view cpy.c @ 2:0b424b791e12

Uploaded
author david-hoover
date Tue, 28 Feb 2012 12:32:29 -0500
parents
children
line wrap: on
line source

#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <pwd.h>
#include <grp.h> // declares struct group
#include <libgen.h> // for dirname
#include <string.h> // for strcpy

/* cpy.c  David Hoover  1/20/12
usage:
  cpy from.file to.file login

cpy copies a file from one location to another, and then sets the ownership to a given user.  The
program is expected to be setuid and owned by root.

*/

int notWriteable(char *file, char *user)
/* Returns 1 if file not writeable by given user */
{
    struct stat fileStat;
    struct passwd *own,*usr;
    struct group *grp;
    int i=0;

    usr = getpwnam(user);

/* does user exist? */
    if (! usr)
    {
        fprintf(stderr,"%s: No such user\n",user);
        exit(1);
    }

/* must be able to stat file */
    if (stat(file, &fileStat) < 0)
    {
        fprintf(stderr,"%s: No such directory\n",file);
        exit(1);
    }

/* get the owner and group information for the file */
    own = getpwuid(fileStat.st_uid);
    grp = getgrgid(fileStat.st_gid);

/* does the file owner match the argument? */
//    if (!strcmp(own->pw_name,user))
    if (usr->pw_uid == fileStat.st_uid)
    {
//        printf("owners match!\n");

/* is file writeable? */
        if (fileStat.st_mode & S_IWUSR)
        {
//            printf("%s is writeable by %s\n",file,user);
            return 0;
        }
        else
        {
//            printf("%s is not writeable by %s\n",file,user);
        }
    }
    else {
//        printf("owners don't match!\n");
    }

/* is the file group readable by the given group? */
    if (fileStat.st_mode & S_IWGRP)
    {
//        printf("%s is writeable by group %s\n",file,grp->gr_name);


/* is the user's gid the same as the file? */
//        printf("%d\n",usr->pw_gid);
//        printf("%d\n",fileStat.st_gid);
        if (usr->pw_gid == fileStat.st_gid)
        {
//            printf("groups match!\n");

/* if the path a directory is it executable? */
            if (S_ISDIR(fileStat.st_mode))
            {
                if (fileStat.st_mode & S_IXGRP)
                {
                    return 0;
                }
            }
            else {
                return 0;
            }
        }
        else
        {

/* is the user a member of the group that owns the file? */
            while(grp->gr_mem[i] != NULL)
            {
                if(!strcmp(grp->gr_mem[i],user))
                {
//                    printf("%s is a member of the %s group\n",user,grp->gr_name);
/* if the path a directory is it executable? */
                    if (S_ISDIR(fileStat.st_mode))
                    {
                        if (fileStat.st_mode & S_IXGRP)
                        {
                            return 0;
                        }
                    }
                    else {
                        return 0;
                    }
                }
                i++;
            }
    
//            printf("%s is not a member of the %s group\n",user,grp->gr_name);

        }
    }
    else
    {
//        printf("%s is not writeable by group %s\n",file,grp->gr_name);
    }

/* is the e world writeable? */
    if (fileStat.st_mode & S_IWOTH)
    {
//        printf("%s is world writeable\n",file);
        return 0;
    }
    else
    {
//        printf("%s is not world writeable\n",file);
    }

    return 1;
}

int notReadable(char *file, char *user)
/* Returns 1 if file not readable by given user */
{
    struct stat fileStat;
    struct passwd *own,*usr;
    struct group *grp;
    int i=0;

    usr = getpwnam(user);

/* does user exist? */
    if (! usr)
    {
        fprintf(stderr,"%s: No such user\n",user);
        exit(1);
    }

/* must be able to stat file */
    if (stat(file, &fileStat) < 0)
    {
        fprintf(stderr,"%s: No such directory\n",file);
        exit(1);
    }

/* get the owner and group information for the file */
    own = getpwuid(fileStat.st_uid);
    grp = getgrgid(fileStat.st_gid);

/* does the file owner match the argument? */
//    if (!strcmp(own->pw_name,user))
    if (usr->pw_uid == fileStat.st_uid)
    {
//        printf("owners match!\n");

/* is file readable? */
        if (fileStat.st_mode & S_IRUSR)
        {
//            printf("%s is readable by %s\n",file,user);
            return 0;
        }
        else
        {
//            printf("%s is not readable by %s\n",file,user);
        }
    }
    else {
//        printf("owners don't match!\n");
    }

/* is the file group readable by the given group? */
    if (fileStat.st_mode & S_IRGRP)
    {
//        printf("%s is readable by group %s\n",file,grp->gr_name);


/* is the user's gid the same as the file? */
//        printf("%d\n",usr->pw_gid);
//        printf("%d\n",fileStat.st_gid);
        if (usr->pw_gid == fileStat.st_gid)
        {
//            printf("groups match!\n");

/* if the path a directory is it executable? */
            if (S_ISDIR(fileStat.st_mode))
            {
                if (fileStat.st_mode & S_IXGRP)
                {
                    return 0;
                }
            }
            else {
                return 0;
            }
        }
        else
        {

/* is the user a member of the group that owns the file? */
            while(grp->gr_mem[i] != NULL)
            {
                if(!strcmp(grp->gr_mem[i],user))
                {
//                    printf("%s is a member of the %s group\n",user,grp->gr_name);
/* if the path a directory is it executable? */
                    if (S_ISDIR(fileStat.st_mode))
                    {
                        if (fileStat.st_mode & S_IXGRP)
                        {
                            return 0;
                        }
                    }
                    else {
                        return 0;
                    }
                }
                i++;
            }
    
//            printf("%s is not a member of the %s group\n",user,grp->gr_name);

        }
    }
    else
    {
//        printf("%s is not readable by group %s\n",file,grp->gr_name);
    }

/* is the e world readable? */
    if (fileStat.st_mode & S_IROTH)
    {
//        printf("%s is world readable\n",file);
        return 0;
    }
    else
    {
//        printf("%s is not world readable\n",file);
    }

    return 1;
}

int copyFile(char *src, char *dst)
{
//    printf("Copying %s to %s\n",src,dst);

    int c;
    FILE *fs,*ft;
    struct stat fileStat;

/* must be able to stat file */
    if (stat(src, &fileStat) < 0)
    {
        fprintf(stderr,"%s: No such file\n",src);
        exit(1);
    }

/* is path a regular file? */
    if (S_ISDIR(fileStat.st_mode))
    {
        fprintf(stderr,"%s: Is a directory\n",src);
        exit(1);
    }

    fs = fopen(src,"r");
    if (fs==NULL) {
        fprintf(stderr,"Can't read from file %s!\n",src);
        exit(1);
    }
    ft = fopen(dst,"w");
    if (ft==NULL) {
        fprintf(stderr,"Can't write to file %s!\n",dst);
        exit(1);
    }

    c = getc(fs);
    while (c != EOF) {
        putc(c,ft);
        c = getc(fs);
   }

   fclose(fs);
   fclose(ft);

   return 0;

}

int chownToGivenUser(char *file, char *user)
/* chown a file to the given user */
{
  struct passwd *usr;

  usr = getpwnam(user);

//  printf("UID = %d\n",usr->pw_uid);
//  printf("GID = %d\n",usr->pw_gid);

//  printf("chown %s %d,%d\n",file,usr->pw_uid,usr->pw_gid);
  if (chown(file,usr->pw_uid,usr->pw_gid))
  {
      fprintf(stderr,"Can't chown %s\n",file);
      exit(1);
  }
  return 0;
}

int explodePath(char *file, char *user)
/* Returns 1 if file not readable by given user */
{
    char **path;
    char *dir;
    char newfile[10000];
    int i;

    strcpy(newfile,file);
    if (!notReadable(newfile,user))
    {
      dir = dirname(newfile);
      if (strcmp(dir,"/"))
        explodePath(dir,user);
    }
    else
    {
        fprintf(stderr,"%s: Permission denied.\n",file);
        exit(1);
    }

    return 0;
}

main(int argc, char **argv)
{
    char *dir;
    char newfile[10000];
    struct stat fileStat;

/* must have two arguments */
    if (argc != 4)
    {
        fprintf(stderr,"usage: cpy source dest user\n");
        exit(1);
    }

/* is filepath writeable by given user? */
    strcpy(newfile,argv[2]);
    dir = dirname(newfile);
    if (!notWriteable(dir,argv[3]))
    { 
 
/* is filepath readable by given user? */
      explodePath(dir,argv[3]);

/* dest file must not exist yet */
    if (!(stat(argv[2], &fileStat) < 0))
    {
        fprintf(stderr,"%s: File already exists.\n",argv[2]);
        exit(1);
    }

/* copy the file and change the owner */
      copyFile(argv[1],argv[2]);
      chownToGivenUser(argv[2],argv[3]);
    }
    else 
    {
      fprintf(stderr,"%s: Permission denied.\n",argv[2]);
      exit(1);
    }

    exit(0);
}