Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
bgColor#ccccff
#include <stdlib.h>
#include <unistd.h>
#include <libgen.h>
#include <sys/stat.h>

int secure_dir(const char* path) {
  char *realpath_res = realpath(path, NULL);
  char *path_copy = NULL;
  char *dirname_res = NULL;
  char ** dirs;
  int num_of_dirs = 0;
  int insecure = 0;
  int i;
  struct stat buf;
  uid_t my_uid = getuid();
  uid_t my_gid = getgid();

  if (realpath_res == NULL) {
    /* Handle Error */
  }

  if (!(path_copy = strdup(path))) {
    /* Handle Error */
  }

  /* Figure out how far it is to the root */
  while (1) {
    dirname_res = dirname(path_copy);
    free(path_copy);
    path_copy = NULL;

    num_of_dirs++;

    if ((strcmp(dirname_res, ".") == 0)
    ||  (strcmp(dirname_res, "/") == 0)) {
      break;
    }

    if (!(path_copy = strdup(dirname_res))) {
      /* Handle Error */
    }
  }
  free(path_copy);
  path_copy = NULL;

  /* Now allocate and fill the dirs array */
  if (!(dirs = (char **) malloc(num_of_dirs*sizeof(*dirs)))) {
    /* Handle Error */
  }
  if (!(dirs[num_of_dirs - 1] = strdup(path))) {
    /* Handle Error */
  }

  if (!(path_copy = strdup(path))) {
    /* Handle Error */
  }

  for (i = 1; i < num_of_dirs; i++) {
    dirname_res = dirname(path_copy);
    free(path_copy);
    path_copy = NULL;

    if (!(dirs[num_of_dirs - i - 1] = strdup(dirname_res))) {
      /* Handle Error */
    }

    if (!(path_copy = strdup(dirname_res))) {
      /* Handle Error */
    }
  }
  free(path_copy);
  path_copy = NULL;

  /* Traverse from the root to the top, checking
   * permissions along the way */
  for (i = 0; i < num_of_dirs; i++) {
    if (stat(dirs[i], &buf) != 0) {
       /* Handle Error */
    }
    if (!((buf.st_uid == my_uid) || (buf.st_uid == 0)
        ||(buf.st_gid == my_gid) || (buf.st_gid == 0)
        ||(buf.st_mode & S_IRWXO))) {
      /* Directory is owned or has a group other than root
       * or file is accessible by other users */
      insecure = -1;
    }
    free(dirs[i]);
    dirs[i] = NULL;
  }
  free(dirs);
  dirs = NULL;

  return insecure;
}

...