Ejemplo n.º 1
0
Archivo: fancyCat.c Proyecto: CPLUG/cpc
int main(int argc, char *argv[]) {
    char *user = getpwuid(getuid())->pw_name;
    char *competition, *problem, *file;
    FILE *f;
    int i, c;
    
    if (argc != 4) {
        puts("Error: Not enough arguments");
        exit(-1);
    }
    
    competition = basename(argv[1]);
    problem = basename(argv[2]);
    file = basename(argv[3]);
    
    chdir(PROBLEMS_LOC);
    safe_chdir(competition);
    safe_chdir(problem);
    chdir("submissions/queued");
    mkdir(user, S_IRWXU|S_IRGRP|S_IXGRP);
    safe_chdir(user);
    
    f = fopen(file, "w+");
    for (i = 0; i < MAX_FILESIZE && (c = getchar()) != EOF; i++)
        fputc(c, f);
    if (i == MAX_FILESIZE)
        printf("Error: File was too large. Max filesize is: %d", MAX_FILESIZE);
    fclose(f);
}
Ejemplo n.º 2
0
void
changedir(const char *path) {
    static int round = 0;
    printf("------------------------\n");
    safe_chdir(path);
    safe_getcwd(round);
    safe_lsdir(round);
    round ++;
}
Ejemplo n.º 3
0
/**
* pm_execute
* @params
*   int should_wait - Indicates if this execute should be inline or asynchronous
*   const char* command - The command to run
*   const char* cd - Run in this directory unless it's a NULL pointer
*   int nice - Special nice level
*   const char** env - Environment variables to run in the shell
* @output
    pid_t pid - output pid of the new process
**/
pid_t pm_execute(
  int should_wait, const char* command, const char *cd, int nice, const char** env, int *child_stdin, const char* p_stdout, const char *p_stderr
) {
  // Setup execution
  char **command_argv = {0};
  int command_argc = 0;
  int running_script = 0;
  int countdown = 200;
  
  // If there is nothing here, don't run anything :)
  if (strlen(command) == 0) return -1;
  
  char* chomped_string = str_chomp(command);
  char* safe_chomped_string = str_safe_quote(chomped_string);
  if (expand_command((const char*)safe_chomped_string, &command_argc, &command_argv, &running_script, env)) ;
  command_argv[command_argc] = 0;
      
  // Now actually RUN it!
  pid_t pid;
  
#if USE_PIPES

  int child_fd[2];
  if ( pipe(child_fd) < 0 ) {// Create a pipe to the child (do we need this? I doubt it)
    perror("pipe failed");
  }
  // Setup the stdin so the parent can communicate!
  (*child_stdin) = child_fd[0];
#endif

    // Let's name it so we can get to it later
  int child_dev_null;
  
#if DEBUG
  if ((child_dev_null = open("debug.log", O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0) {
    syslog(LOG_ERR, "babysitter (fatal): Could not open debug.log: errno: %d\n", errno);
  };
#else
  if ((child_dev_null = open("/dev/null", O_RDWR)) < 0) {
    syslog(LOG_ERR, "babysitter (fatal): Could not open /dev/null: errno: %d\n", errno);
  };
#endif
    
  // Setup fork
  pm_setup_fork();
  
  if (should_wait)
    pid = vfork();
  else
    pid = fork();
    
  switch (pid) {
  case -1: 
    return -1;
  case 0: {
    // Child process
    pm_setup_child();
    
    if (cd != NULL && cd[0] != '\0')
      safe_chdir(cd);
    else
      safe_chdir("/tmp");
        
    int child_stdout, child_stderr;
    // Set everything to dev/null first
    child_stdout = child_stderr = child_dev_null;
    
    // If we've passed in a stdout filename, then open it
    if(p_stdout)
      if ((child_stdout = open(p_stdout, O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0) {
        perror("child stdout");
        child_stdout = child_dev_null;
      }
    // If we've been passed a stderr filename, then open that
    if(p_stderr)
      if ((child_stderr = open(p_stderr, O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0) {
        perror("child stderr");
        child_stderr = child_dev_null;
      }
    
    // Parent doesn't write anything to the child, so just close this right away
    // REDIRECT TO DEV/NULL
    // Replace the stdout/stderr with the child_write fd
#if USE_PIPES
    if (dup2(child_fd[0], STDIN_FILENO) < 0)       FATAL_ERROR("could not dup STDIN_FILENO", -1);
    close(child_fd[1]); // We are using a different stdout
#endif

#if DEBUG
#else
    // Setup the different stdout/stderr
    if (dup2(child_stdout, STDOUT_FILENO) < 0)  FATAL_ERROR("could not dup STDOUT_FILENO", -1);
    if (dup2(child_stderr, STDERR_FILENO) < 0)  FATAL_ERROR("could not dup STDERR_FILENO", -1);

    if (child_stdout != child_dev_null) close(child_stdout);
    if (child_stderr != child_dev_null) close(child_stderr);
#endif

    if (execve((const char*)command_argv[0], command_argv, (char* const*) env) < 0) {
      perror("execve");
      exit(-1);
    }
  }
  default:
    // In parent process
    // set the stdout back
    close(child_dev_null); // Child write never gets used outside the child
  
#if USE_PIPES
    if (dup2(child_fd[1], STDOUT_FILENO) < 0)
      perror("dup2");
    
    close(child_fd[0]);
#endif
    
    if (nice != INT_MAX && setpriority(PRIO_PROCESS, pid, nice) < 0) 
      ;
    if (running_script) {
      while (countdown > 0) {
        if (kill(pid, 0) != 0) break;
        usleep(100);
        countdown--;
      }
      struct stat buffer;
      if (stat(command_argv[0], &buffer) != 0) {
        printf("file doesn't exist when it should because: %s\n", strerror(errno));
      }
      if( unlink( command_argv[0] ) != 0 ) perror( "Error deleting file" );
    }
    // These are free'd later, anyway
    // if (chomped_string) free(chomped_string); 
    // if (safe_chomped_string) free(safe_chomped_string);
    return pid;
  }
}
Ejemplo n.º 4
0
static PromiseResult VerifyFilePromise(EvalContext *ctx, char *path, const Promise *pp)
{
    struct stat osb, oslb, dsb;
    CfLock thislock;
    int exists;

    Attributes a = GetFilesAttributes(ctx, pp);

    if (!FileSanityChecks(ctx, path, a, pp))
    {
        return PROMISE_RESULT_NOOP;
    }

    EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "promiser", path, DATA_TYPE_STRING, "source=promise");

    thislock = AcquireLock(ctx, path, VUQNAME, CFSTARTTIME, a.transaction, pp, false);
    if (thislock.lock == NULL)
    {
        return PROMISE_RESULT_SKIPPED;
    }

    LoadSetuid(a);

    PromiseResult result = PROMISE_RESULT_NOOP;
    if (lstat(path, &oslb) == -1)       /* Careful if the object is a link */
    {
        if ((a.create) || (a.touch))
        {
            if (!CfCreateFile(ctx, path, pp, a, &result))
            {
                goto exit;
            }
            else
            {
                exists = (lstat(path, &oslb) != -1);
            }
        }

        exists = false;
    }
    else
    {
        if ((a.create) || (a.touch))
        {
            cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "File '%s' exists as promised", path);
        }
        exists = true;
    }

    if ((a.havedelete) && (!exists))
    {
        cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "File '%s' does not exist as promised", path);
        goto exit;
    }

    if (!a.havedepthsearch)     /* if the search is trivial, make sure that we are in the parent dir of the leaf */
    {
        char basedir[CF_BUFSIZE];

        Log(LOG_LEVEL_DEBUG, "Direct file reference '%s', no search implied", path);
        snprintf(basedir, sizeof(basedir), "%s", path);

        if (strcmp(ReadLastNode(basedir), ".") == 0)
        {
            // Handle /.  notation for deletion of directories
            ChopLastNode(basedir);
            ChopLastNode(path);
        }

        ChopLastNode(basedir);
        if (safe_chdir(basedir))
        {
            Log(LOG_LEVEL_ERR, "Failed to chdir into '%s'", basedir);
        }
    }

    /* If file or directory exists but it is not selected by body file_select
     * (if we have one) then just exit. But continue if it's a directory and
     * depth_search is on, so that we can file_select into it. */
    if (exists && (!VerifyFileLeaf(ctx, path, &oslb, a, pp, &result)) &&
        !(a.havedepthsearch && S_ISDIR(oslb.st_mode)))
    {
        goto exit;
    }

    if (stat(path, &osb) == -1)
    {
        if ((a.create) || (a.touch))
        {
            if (!CfCreateFile(ctx, path, pp, a, &result))
            {
                goto exit;
            }
            else
            {
                exists = true;
            }
        }
        else
        {
            exists = false;
        }
    }
    else
    {
        if (!S_ISDIR(osb.st_mode))
        {
            if (a.havedepthsearch)
            {
                Log(LOG_LEVEL_WARNING,
                    "depth_search (recursion) is promised for a base object '%s' that is not a directory",
                      path);
                goto exit;
            }
        }

        exists = true;
    }

    if (a.link.link_children)
    {
        if (stat(a.link.source, &dsb) != -1)
        {
            if (!S_ISDIR(dsb.st_mode))
            {
                Log(LOG_LEVEL_ERR, "Cannot promise to link the children of '%s' as it is not a directory!",
                      a.link.source);
                goto exit;
            }
        }
    }

/* Phase 1 - */

    if (exists && ((a.havedelete) || (a.haverename) || (a.haveperms) || (a.havechange) || (a.transformer)))
    {
        lstat(path, &oslb);     /* if doesn't exist have to stat again anyway */

        DepthSearch(ctx, path, &oslb, 0, a, pp, oslb.st_dev, &result);

        /* normally searches do not include the base directory */

        if (a.recursion.include_basedir)
        {
            int save_search = a.havedepthsearch;

            /* Handle this node specially */

            a.havedepthsearch = false;
            DepthSearch(ctx, path, &oslb, 0, a, pp, oslb.st_dev, &result);
            a.havedepthsearch = save_search;
        }
        else
        {
            /* unless child nodes were repaired, set a promise kept class */
            if (!IsDefinedClass(ctx, "repaired"))
            {
                cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "Basedir '%s' not promising anything", path);
            }
        }

        if (((a.change.report_changes) == FILE_CHANGE_REPORT_CONTENT_CHANGE) || ((a.change.report_changes) == FILE_CHANGE_REPORT_ALL))
        {
            if (a.havedepthsearch)
            {
                PurgeHashes(ctx, NULL, a, pp);
            }
            else
            {
                PurgeHashes(ctx, path, a, pp);
            }
        }
    }

/* Phase 2a - copying is potentially threadable if no followup actions */

    if (a.havecopy)
    {
        result = PromiseResultUpdate(result, ScheduleCopyOperation(ctx, path, a, pp));
    }

/* Phase 2b link after copy in case need file first */

    if ((a.havelink) && (a.link.link_children))
    {
        result = PromiseResultUpdate(result, ScheduleLinkChildrenOperation(ctx, path, a.link.source, 1, a, pp));
    }
    else if (a.havelink)
    {
        result = PromiseResultUpdate(result, ScheduleLinkOperation(ctx, path, a.link.source, a, pp));
    }

/* Phase 3 - content editing */

    if (a.haveedit)
    {
        if (exists)
        {
            result = PromiseResultUpdate(result, ScheduleEditOperation(ctx, path, a, pp));
        }
        else
        {
            cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Promised to edit '%s', but file does not exist", path);
            result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL);
        }
    }

// Once more in case a file has been created as a result of editing or copying

    exists = (stat(path, &osb) != -1);

    if (exists && (S_ISREG(osb.st_mode)))
    {
        VerifyFileLeaf(ctx, path, &osb, a, pp, &result);
    }

    if (!exists && a.havechange)
    {
        cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Promised to monitor '%s' for changes, but file does not exist", path);
        result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL);
    }

exit:

    if (AttrHasNoAction(a))
    {
        Log(LOG_LEVEL_INFO,
            "No action was requested for file '%s'. Maybe a typo in the policy?", path);
    }

    result = PromiseResultUpdate(result, SaveSetuid(ctx, a, pp));
    YieldCurrentLock(thislock);

    return result;
}
Ejemplo n.º 5
0
FILE *cf_popen_shsetuid(const char *command, const char *type, uid_t uid, gid_t gid, char *chdirv, char *chrootv, ARG_UNUSED int background)
{
    int pd[2];
    pid_t pid;
    FILE *pp = NULL;

    pid = CreatePipeAndFork(type, pd);
    if (pid == -1) {
        return NULL;
    }

    if (pid == 0)
    {
        switch (*type)
        {
        case 'r':

            close(pd[0]);       /* Don't need output from parent */

            if (pd[1] != 1)
            {
                dup2(pd[1], 1); /* Attach pp=pd[1] to our stdout */
                dup2(pd[1], 2); /* Merge stdout/stderr */
                close(pd[1]);
            }

            break;

        case 'w':

            close(pd[1]);

            if (pd[0] != 0)
            {
                dup2(pd[0], 0);
                close(pd[0]);
            }
        }

        CloseChildrenFD();

        if (chrootv && (strlen(chrootv) != 0))
        {
            if (chroot(chrootv) == -1)
            {
                Log(LOG_LEVEL_ERR, "Couldn't chroot to '%s'. (chroot: %s)", chrootv, GetErrorStr());
                return NULL;
            }
        }

        if (chdirv && (strlen(chdirv) != 0))
        {
            if (safe_chdir(chdirv) == -1)
            {
                Log(LOG_LEVEL_ERR, "Couldn't chdir to '%s'. (chdir: %s)", chdirv, GetErrorStr());
                return NULL;
            }
        }

        if (!CfSetuid(uid, gid))
        {
            _exit(EXIT_FAILURE);
        }

        execl(SHELL_PATH, "sh", "-c", command, NULL);
        _exit(EXIT_FAILURE);
    }
    else
    {
        switch (*type)
        {
        case 'r':

            close(pd[1]);

            if ((pp = fdopen(pd[0], type)) == NULL)
            {
                cf_pwait(pid);
                return NULL;
            }
            break;

        case 'w':

            close(pd[0]);

            if ((pp = fdopen(pd[1], type)) == NULL)
            {
                cf_pwait(pid);
                return NULL;
            }
        }

        SetChildFD(fileno(pp), pid);
        return pp;
    }

    return NULL;
}