Example #1
0
/* Create a pipe with one inheritable end.  Default implementation.
   If INHERIT_IDX is 0, the read end of the pipe is made inheritable;
   with INHERIT_IDX is 1 the write end will be inheritable.  The
   question now is how we create an inheritable pipe end under windows
   CE were handles are process local objects?  The trick we employ is
   to defer the actual creation to the other end: We create an
   incomplete pipe and pass a rendezvous id to the other end
   (process).  The other end now uses the rendezvous id to lookup the
   pipe in our device driver, creates a new handle and uses that one
   to finally establish the pipe.  */
int
__assuan_pipe (assuan_context_t ctx, assuan_fd_t fd[2], int inherit_idx)
{
  HANDLE hd;
  int rvid;

  hd = _assuan_w32ce_prepare_pipe (&rvid, !inherit_idx);
  if (hd == INVALID_HANDLE_VALUE)
    {
      TRACE1 (ctx, ASSUAN_LOG_SYSIO, "__assuan_pipe", ctx,
	      "CreatePipe failed: %s", _assuan_w32_strerror (ctx, -1));
      gpg_err_set_errno (EIO);
      return -1;
    }

  if (inherit_idx)
    {
      fd[0] = hd;
      fd[1] = (void*)rvid;
    }
  else
    {
      fd[0] = (void*)rvid;
      fd[1] = hd;
    }
  return 0;
}
Example #2
0
/* Create a pipe with one inheritable end.  Default implementation.  */
int
__assuan_pipe (assuan_context_t ctx, assuan_fd_t fd[2], int inherit_idx)
{
    HANDLE rh;
    HANDLE wh;
    HANDLE th;
    SECURITY_ATTRIBUTES sec_attr;

    memset (&sec_attr, 0, sizeof (sec_attr));
    sec_attr.nLength = sizeof (sec_attr);
    sec_attr.bInheritHandle = FALSE;

    if (!CreatePipe (&rh, &wh, &sec_attr, 0))
    {
        TRACE1 (ctx, ASSUAN_LOG_SYSIO, "__assuan_pipe", ctx,
                "CreatePipe failed: %s", _assuan_w32_strerror (ctx, -1));
        gpg_err_set_errno (EIO);
        return -1;
    }

    if (! DuplicateHandle (GetCurrentProcess(), (inherit_idx == 0) ? rh : wh,
                           GetCurrentProcess(), &th, 0,
                           TRUE, DUPLICATE_SAME_ACCESS ))
    {
        TRACE1 (ctx, ASSUAN_LOG_SYSIO, "__assuan_pipe", ctx,
                "DuplicateHandle failed: %s", _assuan_w32_strerror (ctx, -1));
        CloseHandle (rh);
        CloseHandle (wh);
        gpg_err_set_errno (EIO);
        return -1;
    }
    if (inherit_idx == 0)
    {
        CloseHandle (rh);
        rh = th;
    }
    else
    {
        CloseHandle (wh);
        wh = th;
    }

    fd[0] = rh;
    fd[1] = wh;

    return 0;
}
Example #3
0
int
__assuan_spawn (assuan_context_t ctx, pid_t *r_pid, const char *name,
                const char **argv,
                assuan_fd_t fd_in, assuan_fd_t fd_out,
                assuan_fd_t *fd_child_list,
                void (*atfork) (void *opaque, int reserved),
                void *atforkvalue, unsigned int flags)
{
    SECURITY_ATTRIBUTES sec_attr;
    PROCESS_INFORMATION pi =
    {
        NULL,      /* Returns process handle.  */
        0,         /* Returns primary thread handle.  */
        0,         /* Returns pid.  */
        0          /* Returns tid.  */
    };
    STARTUPINFO si;
    assuan_fd_t fd;
    assuan_fd_t *fdp;
    char *cmdline;
    HANDLE nullfd = INVALID_HANDLE_VALUE;

    /* fixme: Actually we should set the "_assuan_pipe_connect_pid" env
       variable.  However this requires us to write a full environment
       handler, because the strings are expected in sorted order.  The
       suggestion given in the MS Reference Library, to save the old
       value, change it, create process and restore it, is not thread
       safe.  */

    /* Build the command line.  */
    if (build_w32_commandline (ctx, argv, &cmdline))
        return -1;

    /* Start the process.  */
    memset (&sec_attr, 0, sizeof sec_attr);
    sec_attr.nLength = sizeof sec_attr;
    sec_attr.bInheritHandle = FALSE;

    memset (&si, 0, sizeof si);
    si.cb = sizeof (si);
    si.dwFlags = STARTF_USESTDHANDLES;
    /* FIXME: Dup to nul if ASSUAN_INVALID_FD.  */
    si.hStdInput  = fd_in;
    si.hStdOutput = fd_out;

    /* Dup stderr to /dev/null unless it is in the list of FDs to be
       passed to the child. */
    fd = assuan_fd_from_posix_fd (fileno (stderr));
    fdp = fd_child_list;
    if (fdp)
    {
        for (; *fdp != ASSUAN_INVALID_FD && *fdp != fd; fdp++)
            ;
    }
    if (!fdp || *fdp == ASSUAN_INVALID_FD)
    {
        nullfd = CreateFileW (L"nul", GENERIC_WRITE,
                              FILE_SHARE_READ | FILE_SHARE_WRITE,
                              NULL, OPEN_EXISTING, 0, NULL);
        if (nullfd == INVALID_HANDLE_VALUE)
        {
            TRACE1 (ctx, ASSUAN_LOG_SYSIO, "__assuan_spawn", ctx,
                    "can't open `nul': %s", _assuan_w32_strerror (ctx, -1));
            _assuan_free (ctx, cmdline);
            gpg_err_set_errno (EIO);
            return -1;
        }
        si.hStdError = nullfd;
    }
    else
        si.hStdError = fd;

    /* Note: We inherit all handles flagged as inheritable.  This seems
       to be a security flaw but there seems to be no way of selecting
       handles to inherit.  A fix for this would be to use a helper
       process like we have in gpgme.  */
    /*   _assuan_log_printf ("CreateProcess, path=`%s' cmdline=`%s'\n", */
    /*                       name, cmdline); */
    if (!CreateProcess (name,                 /* Program to start.  */
                        cmdline,              /* Command line arguments.  */
                        &sec_attr,            /* Process security attributes.  */
                        &sec_attr,            /* Thread security attributes.  */
                        TRUE,                 /* Inherit handles.  */
                        (CREATE_DEFAULT_ERROR_MODE
                         | ((flags & 128)? DETACHED_PROCESS : 0)
                         | GetPriorityClass (GetCurrentProcess ())
                         | CREATE_SUSPENDED), /* Creation flags.  */
                        NULL,                 /* Environment.  */
                        NULL,                 /* Use current drive/directory.  */
                        &si,                  /* Startup information. */
                        &pi                   /* Returns process information.  */
                       ))
    {
        TRACE1 (ctx, ASSUAN_LOG_SYSIO, "pipe_connect_w32", ctx,
                "CreateProcess failed: %s", _assuan_w32_strerror (ctx, -1));
        _assuan_free (ctx, cmdline);
        if (nullfd != INVALID_HANDLE_VALUE)
            CloseHandle (nullfd);

        gpg_err_set_errno (EIO);
        return -1;
    }

    _assuan_free (ctx, cmdline);
    if (nullfd != INVALID_HANDLE_VALUE)
        CloseHandle (nullfd);

    ResumeThread (pi.hThread);
    CloseHandle (pi.hThread);

    /*   _assuan_log_printf ("CreateProcess ready: hProcess=%p hThread=%p" */
    /*                       " dwProcessID=%d dwThreadId=%d\n", */
    /*                       pi.hProcess, pi.hThread, */
    /*                       (int) pi.dwProcessId, (int) pi.dwThreadId); */

    *r_pid = (pid_t) pi.hProcess;

    /* No need to modify peer process, as we don't change the handle
       names.  However this also means we are not safe, as we inherit
       too many handles.  Should use approach similar to gpgme and glib
       using a helper process.  */

    return 0;
}
Example #4
0
int
__assuan_spawn (assuan_context_t ctx, pid_t *r_pid, const char *name,
		const char **argv,
		assuan_fd_t fd_in, assuan_fd_t fd_out,
		assuan_fd_t *fd_child_list,
		void (*atfork) (void *opaque, int reserved),
		void *atforkvalue, unsigned int flags)
{
  PROCESS_INFORMATION pi = 
    {
      NULL,      /* Returns process handle.  */
      0,         /* Returns primary thread handle.  */
      0,         /* Returns pid.  */
      0          /* Returns tid.  */
    };
  assuan_fd_t fd;
  assuan_fd_t *fdp;
  assuan_fd_t fd_err;
  int fd_err_isnull = 0;
  char *cmdline;

  /* Dup stderr to /dev/null unless it is in the list of FDs to be
     passed to the child.  Well we don't actually open nul because
     that is not available on Windows, but use our hack for it.
     Because an RVID of 0 is an invalid value and HANDLES will never
     have this value either, we test for this as well.  */

  /* FIXME: As long as we can't decide whether a handle is a real
     handler or an rendezvous id we can't do anything with the
     FD_CHILD_LIST.  We can't do much with stderr either, thus we
     better don't pass stderr to the child at all.  If we would do so
     and it is not a rendezvous id the client would run into
     problems.  */
  fd = assuan_fd_from_posix_fd (fileno (stderr));
  fdp = fd_child_list;
  if (fdp)
    {
      for (; *fdp != ASSUAN_INVALID_FD && *fdp != 0 && *fdp != fd; fdp++)
        ;
    }
  if (!fdp || *fdp == ASSUAN_INVALID_FD)
    fd_err_isnull = 1;
  fd_err = ASSUAN_INVALID_FD;

  if (build_w32_commandline (ctx, argv, fd_in, fd_out, fd_err, fd_err_isnull,
                             &cmdline))
    {
      return -1;
    }

  TRACE2 (ctx, ASSUAN_LOG_SYSIO, "__assuan_spawn", ctx,
          "path=`%s' cmdline=`%s'", name, cmdline);

  {
    wchar_t *wcmdline, *wname;

    wcmdline = utf8_to_wchar (cmdline);
    _assuan_free (ctx, cmdline);
    if (!wcmdline)
      return -1;

    wname = utf8_to_wchar (name);
    if (!wname)
      {
        free_wchar (wcmdline);
        return -1;
      }
    
    if (!CreateProcess (wname,                /* Program to start.  */
                        wcmdline,             /* Command line arguments.  */
                        NULL,                 /* (not supported)  */
                        NULL,                 /* (not supported)  */
                        FALSE,                /* (not supported)  */
                        (CREATE_SUSPENDED),   /* Creation flags.  */
                        NULL,                 /* (not supported)  */
                        NULL,                 /* (not supported)  */
                        NULL,                 /* (not supported) */
                        &pi                   /* Returns process information.*/
                        ))
      {
        TRACE1 (ctx, ASSUAN_LOG_SYSIO, "__assuan_spawn", ctx,
                "CreateProcess failed: %s", _assuan_w32_strerror (ctx, -1));
        free_wchar (wname);
        free_wchar (wcmdline);
        gpg_err_set_errno (EIO);
        return -1;
      }
    free_wchar (wname);
    free_wchar (wcmdline);
  }

  ResumeThread (pi.hThread);

  TRACE4 (ctx, ASSUAN_LOG_SYSIO, "__assuan_spawn", ctx,
          "CreateProcess ready: hProcess=%p hThread=%p"
          " dwProcessID=%d dwThreadId=%d\n",
          pi.hProcess, pi.hThread, (int) pi.dwProcessId, (int) pi.dwThreadId);

  CloseHandle (pi.hThread); 
  
  *r_pid = (pid_t) pi.hProcess;
  return 0;
}