Logo Search packages:      
Sourcecode: sbrsh version File versions  Download package

sb-exportfs.c

/*
 * sb-exportfs version 0.1
 * 
 * Copyright (c) 2003, 2004 Nokia
 *
 * sb-exportfs is licensed under GPL.
 * You can read the full license at http://www.gnu.org/licenses/gpl.txt
 * 
 */

#define _GNU_SOURCE

#include "types.h"
#include "common.h"
#include "config.h"

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <dirent.h>
#include <pwd.h>


#define SB_USERS_DIR    "/scratchbox/users"
#define SB_HOME_DIR     "/scratchbox/users/%s/home"
#define SB_TARGET_DIR   "/scratchbox/users/%s/targets/%s"
#define SB_TARGETS_DIR  "/scratchbox/users/%s/targets"
#define MOUNT_OPTS      "rw,all_squash,anonuid=%i,anongid=%i"


/*
 * We only allow export that are SB_HOME_DIR, SB_TARGET_DIR or SB_TARGETS_DIR.
 * In the last two we also check that those are not links to anywhere but
 * they are really directories.
 */
static int check_path(const char *path, const char *user, const char *target)
{
      char *homedir;
      char *targetdir;
      char *targetsdir;
      char *mypath;
      char *tmp;
      struct stat filestat;

      homedir = alloca(strlen(SB_HOME_DIR) + strlen(user) + 2);
      targetdir = alloca(strlen(SB_TARGET_DIR) + strlen(user) + strlen(target) + 2);
      targetsdir = alloca(strlen(SB_TARGETS_DIR) + strlen(user) + 2);

      sprintf(homedir, SB_HOME_DIR, user);
      sprintf(targetdir, SB_TARGET_DIR, user, target);
      sprintf(targetsdir, SB_TARGETS_DIR, user);

      mypath = strdupa(path);
      while (mypath[strlen(mypath)] == '/')
            mypath[strlen(mypath)] = '\0';

      /* if sb is istalled correctly then this should always be directory */
      if (strcmp(mypath, homedir) == 0)
            return 0;

      /* we want to test this a bit */
      if (strcmp(mypath, targetdir) == 0) {
            stat(mypath, &filestat);
            if (!S_ISDIR(filestat.st_mode))
                  goto _not_dir;

            tmp = strrchr(mypath, '/');
            if (tmp == NULL) {
                  fprintf(stderr, "Error: Bad path: %s\n", path);
                  return -1337;
            }
            *tmp = '\0';

            stat(tmp, &filestat);
            if (!S_ISDIR(filestat.st_mode))
                  goto _not_dir;

            return 0;
      }

      if (strcmp(mypath, targetsdir) == 0) {
            stat(mypath, &filestat);
            if (!S_ISDIR(filestat.st_mode))
                  goto _not_dir;

            return 0;
      }

      fprintf(stderr, "Error: Not allowed to export %s\n", path);
      printf("homedir: %s\n", homedir);
      printf("targetdir: %s\n", targetdir);
      printf("targetsdir: %s\n", targetsdir);
      return -2;

_not_dir:
      fprintf(stderr, "Error: Not allowed to export %s (not a directory)\n", path);
      return -1;
}

int main(int argc,
       char **argv)
{
      DIR *dir;
      struct dirent *file;
      config_t *cfg;
      pid_t pid;
      int status;

      dir = opendir(SB_USERS_DIR);
      if (dir == NULL) {
            perror("Error: Can't open directory");
            exit(1);
      }

      pid = fork();
      if (pid == 0) {
            execlp("exportfs", "exportfs", "-r", NULL);
            perror("Error: Can't exec exportfs");
      }
      wait(&status);

      while ((file = readdir(dir)) != NULL) {
            char **targets;
            char **p, **q;
            char *sbrsh_config;
            struct passwd *pwds = NULL;

            if (strchr(file->d_name, '.') == file->d_name)
                  continue;

            pwds = getpwnam(file->d_name);
            if (pwds == NULL)
                  continue;

            /* check that .sbrsh file exists */
            sbrsh_config = malloc(strlen(SB_USERS_DIR) +
                              strlen("/home/") +
                              strlen(file->d_name) * 2 +
                              strlen("/.sbrsh") + 4);
            sprintf(sbrsh_config, "%s/%s/home/%s/.sbrsh", SB_USERS_DIR,
                  file->d_name, file->d_name);

            targets = get_targets(sbrsh_config);
            if (!targets) {
                  fprintf(stderr, "Warning: No targets found from %s\n", sbrsh_config);
                  free(sbrsh_config);
                  continue;
            }

            p = targets;
            while (*p != NULL) {
                  cfg = config_alloc();
                  config_read(cfg, sbrsh_config, *p);

                  q = cfg->opts;
                  while (*q != NULL) {
                        if (strncmp(*q, "nfs", 3) == 0) {
                              char *path, *tmp;
                              char *cp, *opts;

                              path = strchr(*q, ':');
                              if (path == NULL) {
                                    fprintf(stderr, "Error: Bad config file: %s\n",
                                                sbrsh_config);
                                    ++q;
                                    continue;
                              }
                              ++path;

                              tmp = find_space(path);
                              if (tmp == NULL) {
                                    fprintf(stderr, "Error: Bad config file: %s\n",
                                                sbrsh_config);
                                    ++q;
                                    continue;
                              }
                              *tmp++ = '\0';

                              /* check the path */
                              if (check_path(path, file->d_name, *p) < 0) {
                                    ++q;
                                    continue;
                              }

                              cp = malloc(strlen(cfg->host) + strlen(path) + 4);
                              sprintf(cp, "%s:/%s", cfg->host, path);

                              opts = malloc(strlen(MOUNT_OPTS) + 11);
                              sprintf(opts, MOUNT_OPTS, pwds->pw_uid, pwds->pw_gid);

                              pid = fork();
                              if (pid == 0) {
                                    execlp("exportfs", "exportfs", "-i", "-o", opts, cp,
                                           NULL);
                                    perror("Error: Can't exec exportfs");
                              }
                              wait(&status);

                              free(cp);
                              free(opts);
                        }

                        ++q;
                  }

                  config_free(cfg);
                  ++p;
            }

            free_vec((void **) targets, NULL);
            free(sbrsh_config);
      }

      closedir(dir);

      return 0;
}


Generated by  Doxygen 1.6.0   Back to index