Re: Secure popen

From: John Viega (viegaat_private)
Date: Tue Jun 19 2001 - 18:14:24 PDT

  • Next message: Kai Schulte: "Re: Secure popen"

    Ok, now that the question is a bit more clear, here is some code that
    should work for what you want to do:
    
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <unistd.h> 
    #include <fcntl.h>
    #include <errno.h>
    #include <stdio.h>
    
    void
    send_string_to_command(char **args, char *str, int *err)
    {
      int pwpd[2];
      int pid;
      FILE *fptr;
    
      *err = 0;
      if(pipe(pwpd) < 0) 
      {
        *err = 1;
        return;
      }
      pid = fork();
      switch(pid)
      {
      case -1:
        close(pwpd[STDIN_FILENO]);
        close(pwpd[STDOUT_FILENO]);
        *err = 2;
        return;
      case 0:
        close(pwpd[STDOUT_FILENO]);
        /* If this is a setuid program, you should drop privileges here. */
        if(dup2(pwpd[STDIN_FILENO], STDIN_FILENO) < 0)
        {
          close(pwpd[STDIN_FILENO]);
          exit(254);
        }
        /* You should also sanitize the environment here. */
        execv(args[0], args);
        exit(255); /* If the execv fails. */
      default:
        close(pwpd[STDIN_FILENO]);
        fcntl(pwpd[STDOUT_FILENO], F_SETFD, FD_CLOEXEC);
        fptr = fdopen(pwpd[STDOUT_FILENO], "wb");
        if(!fptr)
        {
          int old = errno;
          kill(pid, SIGKILL);
          close(pwpd[1]);
          waitpid(pid,0,0);
          errno = old;
          *err = 3;
          return;
        }
        if(!waitpid(pid, err, WNOHANG))
        {
          fprintf(fptr, str); 
          fflush(fptr);
          fclose(fptr);
          waitpid(pid, err, 0);
        }
        return;
      }
    }
    
    If there's a problem with calling the command, such as not passing in
    the full path, the above code can occasionally raise SIGPIPE in the
    parent, but usually will not.  Nonetheless, you should consider
    catching SIGPIPE, at least for the duration of this call.
    
    Below is a little test program.  I ran it as such: "./test /bin/cat"
    
    int 
    main(int argc, char **argv)
    {
      int err;
      if(argc <= 1)
      {
        printf("Need to pass in arguments, being a command to call plus its arguments.\n");
        return 0;
      }
      send_string_to_command(&argv[1], "This is a test.\n", &err);
      if(err) 
      {
        printf("Got Error %d!\n", err);
      }
    }
    
    On Tue, Jun 19, 2001 at 05:06:53PM -0400, Aaron Bentley wrote:
    > Hi,
    > I appreciate the suggestion.  The reason why it doesn't solve my problem is because
    > Sendmail is not the problem.
    > 
    > What I'm really looking for, ideally, is a way to avoid both temporary files and
    > /bin/sh
    > If I use temporary files, I can use them with Sendmail just as easily as with mutt.
    > Or, I can use mutt with popen (which uses /bin/sh).
    > 
    > Two people now have suggested using dup2 and exec, and while they're sort of vague
    > about it, I think they mean this:
    > 1. Create a pipe
    > 2. Write to it
    > 3. Use dup2 to replace stdin with your pipe
    > 4. Exec the program (it will inherit stdin from the calling process--e.g. the pipe)
    > 
    > I'm going to try this, because if it works, I can make a "safe popen" function that I
    > can use ad infinitum.
    > 
    > Aaron
    > 
    > Radu Filip wrote:
    > 
    > > Hi!
    > >
    > > On Tue, 19 Jun 2001, Aaron Bentley wrote:
    > >
    > > > This is what I'm doing, except that I'm calling popen to specify a pipe directly,
    > > > instead of writing the message to a temporary file and then using cat to pipe it
    > > > to the mail client.
    > > > Temporary files have their own fun problems, and originally, I was trying to avoid
    > > > using temporary files by using a pipe instead.
    > >
    > > Yes, it's good to avoid temporary files... Anyway, I did not understand
    > > why this solution is not what you're looking for.
    > 
    > >
    > >
    > > Radu
    > >
    > > --
    > > Radu Filip
    > >                            Network Administrator @ Technical University of Iasi
    > > raduat_private             Information Technology and Communication Center
    > > http://socrate.tuiasi.ro/  cctiat_private | http://ccti.tuiasi.ro/
    > 
    > --
    > Aaron Bentley
    > Manager of Information Technology
    > PanoMetrics, Inc.
    > 
    > 
    
    
    



    This archive was generated by hypermail 2b30 : Tue Jun 19 2001 - 20:24:35 PDT