Search code examples
cfileuser-permissionschroot

How to reject user inputted pathes if outside of a certain directory in C


Ok so I have this C program that takes, as user input, a path to a file. I want to be able to open that file, but only if it's in another path. For example, I have this directory structure:

├── forbidden-file
└── directory1
    ├── permitted-file1
    └── directory2
        └── permitted-file2

and I want to reject any paths that point to outside of directory1, relative to directory1. So stuff like ../forbidden-file and directory2/../../forbidden-file would be rejected, but stuff like permitted-file1, directory2/../permitted-file1, and directory2/permitted-file2 would be allowed.

I've looked into chroot a bit, but that doesn't really suit my needs because I need to only reject the paths inputted by the user while leaving my program free to access any files outside of directory1 in my example.

I'm kinda stumped at the minute, so any help would be greatly appreciated! Thanks for your time and have a nice day.


Solution

  • One proven way of handling such scenarios are through keeping a White List for allowed paths or Black List for not allowed paths. here is a simple hello world on white list as well as black list implementation for your reference.

    #include <stdio.h>
    #include <string.h>
    #include <libgen.h>
    #define ENTRIES (3)
    
    const char *white_list[ENTRIES]={
        "/home/allowed_dir1",
        "/home/allowed_dir2",
        "/home/allowed_dir3"
    };
    
    const char *black_list[ENTRIES]={
        "/home/blocked_dir1",
        "/home/blocked_dir2",
        "/home/blocked_dir3"
    };
    
    int check_white_list(char *dirname){
        int i=0;
        for(i=0;i<ENTRIES;i++){
            if(strcmp(dirname, white_list[i])==0){
                return 0;
            }
        }
        return 1;
    }
    
    int check_black_list(char *dirname){
        int i=0;
        for(i=0;i<ENTRIES;i++){
            if(strcmp(dirname, black_list[i])==0){
                return 0;
            }
        }
        return 1;    
    }
    
    int main(int argc, char *argv[])
    {
        int i = 0;
    
    
        char allowed_file[30] = "/home/allowed_dir0/myfile"; //change paths here for sample
        //get dir name of myfile
        char *dir_name = dirname(allowed_file);
    
        /*
         * white list method
         */    
        if(check_white_list(dir_name)==0){
            printf("match found in white list\n");
        }else{
            printf("match not found in white list\n");
        }
    
        /*
         * black list method
         */    
        if(check_black_list(dir_name)==0){
            printf("march found in black list\n");
        }else{
            printf("match not found in black list\n");
        }
    
        return 0;
    }