Exemplo n.º 1
0
int mailprivacy_spawn_and_wait(char * command, char * passphrase,
    char * stdoutfile, char * stderrfile,
    int * bad_passphrase)
{
#ifdef WIN32
  int res;
  SECURITY_ATTRIBUTES sec_attr;
  PROCESS_INFORMATION pi = 
    {
      NULL,      /* Returns process handle.  */
      0,         /* Returns primary thread handle.  */
      0,         /* Returns pid.  */
      0          /* Returns tid.  */
    };
  STARTUPINFO si;
  int cr_flags;
  HANDLE wp_passphrase[2];
  HANDLE fd_out;
  HANDLE fd_err;
  int code;

  /* Prepare security attributes.  */
  memset (&sec_attr, 0, sizeof sec_attr);
  sec_attr.nLength = sizeof sec_attr;
  sec_attr.bInheritHandle = TRUE;

  fd_out = CreateFile (stdoutfile,
		       GENERIC_READ|GENERIC_WRITE,
		       FILE_SHARE_READ|FILE_SHARE_WRITE,
		       &sec_attr,
		       CREATE_ALWAYS,
		       FILE_ATTRIBUTE_NORMAL,
		       NULL);
  if (fd_out == INVALID_HANDLE_VALUE)
    {
      res = ERROR_PASSPHRASE_FILE;
      goto err;
    }

  fd_err = CreateFile (stderrfile,
		       GENERIC_READ|GENERIC_WRITE,
		       FILE_SHARE_READ|FILE_SHARE_WRITE,
		       &sec_attr,
		       CREATE_ALWAYS,
		       FILE_ATTRIBUTE_NORMAL,
		       NULL);
  if (fd_err == INVALID_HANDLE_VALUE)
    {
      res = ERROR_PASSPHRASE_FILE;
      goto close_out;
    }

  /* Create a pipe for the passphrase.  */
  if (create_inheritable_pipe (wp_passphrase))
    {
      res = ERROR_PASSPHRASE_FILE;
      goto close_err;
    }

  /* Prepare security attributes.  */
  memset (&sec_attr, 0, sizeof sec_attr);
  sec_attr.nLength = sizeof sec_attr;
  sec_attr.bInheritHandle = FALSE;
  
  /* Start the process.  */
  memset (&si, 0, sizeof si);
  si.cb = sizeof (si);
  si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
  si.wShowWindow = DEBUG_W32_SPAWN ? SW_SHOW : SW_MINIMIZE;
  si.hStdInput  = wp_passphrase[0];
  si.hStdOutput = fd_out;
  si.hStdError  = fd_err;

  cr_flags = (CREATE_DEFAULT_ERROR_MODE
              | GetPriorityClass (GetCurrentProcess ())
              | CREATE_SUSPENDED); 
  if (!CreateProcess (NULL,          /* Program to start.  */
                      command,       /* Command line arguments.  */
                      &sec_attr,     /* Process security attributes.  */
                      &sec_attr,     /* Thread security attributes.  */
                      TRUE,          /* Inherit handles.  */
                      cr_flags,      /* Creation flags.  */
                      NULL,          /* Environment.  */
                      NULL,          /* Use current drive/directory.  */
                      &si,           /* Startup information. */
                      &pi            /* Returns process information.  */
                      ))
    {
      CloseHandle (wp_passphrase[0]);
      CloseHandle (wp_passphrase[1]);

      res = ERROR_PASSPHRASE_COMMAND;
      goto close_err;
    }

  /* Close the other end of the pipe.  */
  CloseHandle (wp_passphrase[0]);
  CloseHandle (fd_out);
  CloseHandle (fd_err);
  /* Process has been created suspended; resume it now. */
  ResumeThread (pi.hThread);
  CloseHandle (pi.hThread); 

  if ((passphrase != NULL) && (strlen(passphrase) > 0)) {
    DWORD written;
    WriteFile (wp_passphrase[1], passphrase, strlen(passphrase),
	       &written, NULL);
  }
  else {
    DWORD written;
    /* dummy password */
    WriteFile(wp_passphrase[1], "*dummy*", 7, &written, NULL);
  }
  CloseHandle(wp_passphrase[1]);

  code = WaitForSingleObject (pi.hProcess, INFINITE);
  if (code == WAIT_OBJECT_0)
    {
      DWORD exc;
      if (GetExitCodeProcess (pi.hProcess, &exc))
	{
	  if (exc)
	    *bad_passphrase = 1;
	}
      else
	res = ERROR_PASSPHRASE_COMMAND;
    }
  else
    res = ERROR_PASSPHRASE_COMMAND;

  CloseHandle (pi.hProcess);
  return 0;

 close_err:
  CloseHandle (fd_err);
 close_out:
  CloseHandle (fd_out);
 err:
  return res;
#else
  int res;
  int fd_out;
  int fd_err;
  pid_t pid;
  int passphrase_input[2];
  int r;

  fd_out = open(stdoutfile, O_RDWR | O_CREAT | O_TRUNC, 0600);
  if (fd_out < 0) {
    res = ERROR_PASSPHRASE_FILE;
    goto err;
  }
  
  fd_err = open(stderrfile, O_RDWR | O_CREAT | O_TRUNC, 0600);
  if (fd_err < 0) {
    res = ERROR_PASSPHRASE_FILE;
    goto close_out;
  }
  
  r = pipe(passphrase_input);
  if (r < 0) {
    res = ERROR_PASSPHRASE_FILE;
    goto close_err;
  }
  
  pid = fork();
  switch (pid) {
  case -1:
    {
      close (passphrase_input[0]);
      close (passphrase_input[1]);
      res = ERROR_PASSPHRASE_COMMAND;
      goto close_err;
    }
    
  case 0:
    /* child */
    {
      int status;
      
      /* close unneeded fd */
      close(passphrase_input[1]);
      
      dup2(passphrase_input[0], 0);
      close(passphrase_input[0]);
      dup2(fd_out, 1);
      close(fd_out);
      dup2(fd_err, 2);
      close(fd_err);
      
      status = system(command);
      
      exit(WEXITSTATUS(status));
    }
    break;
    
  default:
    /* parent */
    {
      int status;
      
      /* close unneeded fd */
      close(fd_err);
      close(fd_out);
      close(passphrase_input[0]);
      
      if ((passphrase != NULL) && (strlen(passphrase) > 0)) {
        r = (int) write(passphrase_input[1], passphrase, strlen(passphrase));
        if (r != (int) strlen(passphrase)) {
          close(passphrase_input[1]);
          return ERROR_PASSPHRASE_FILE;
        }
      }
      else {
        /* dummy password */
        r = (int) write(passphrase_input[1], "*dummy*", 7);
        if (r != 7) {
          close(passphrase_input[1]);
          return ERROR_PASSPHRASE_FILE;
        }
      }
      close(passphrase_input[1]);
      
      waitpid(pid, &status, 0);
      
      if (WEXITSTATUS(status) != 0)
        *bad_passphrase = 1;

      return MAIL_NO_ERROR;
    }
    break;
  }
  
 close_err:
  close(fd_err);
 close_out:
  close(fd_out);
 err:
  return res;
#endif
}
Exemplo n.º 2
0
/* Portable function to create a pipe.  Under Windows the read end is
   inheritable (i.e. an rendezvous id).  */
gpg_error_t
gnupg_create_outbound_pipe (int filedes[2])
{
  return create_inheritable_pipe (filedes, 0);
}