diff cpx.c @ 0:c772c8912663

Uploaded
author david-hoover
date Tue, 28 Feb 2012 12:36:45 -0500
parents
children e5a905df7e0b
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cpx.c	Tue Feb 28 12:36:45 2012 -0500
@@ -0,0 +1,251 @@
+#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
+
+/* cpx.c  David Hoover  1/13/11
+usage:
+  cpx from.file to.file login
+
+cpx copies a file from one location to another, but only if the original file is owned by the given login.  The
+program is expected to be setuid and owned by root.
+
+*/
+
+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 file\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 chownToUser(char *file)
+/* chown a file to the user running cpx */
+{
+  uid_t uid;
+  gid_t gid;
+
+  uid = getuid();
+  gid = getgid();
+
+//  printf("UID = %d\n",uid);
+//  printf("GID = %d\n",gid);
+
+//  printf("chown %s %d,%d\n",file,uid,gid);
+  if (chown(file,uid,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)
+{
+
+/* must have two arguments */
+    if (argc != 4)
+    {
+        fprintf(stderr,"usage: cpx source dest user\n");
+        exit(1);
+    }
+
+/* is file readable by given user? */
+    explodePath(argv[1],argv[3]);
+
+/* copy the file and change the owner */
+    copyFile(argv[1],argv[2]);
+    chownToUser(argv[2]);
+
+    exit(0);
+}