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.
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;
}