Ejemplo n.º 1
0
static void
init_membuf (assuan_context_t ctx,
	     struct membuf *mb, int initiallen, size_t maxlen)
{
  mb->len = 0;
  mb->size = initiallen;
  mb->out_of_core = 0;
  mb->too_large = 0;
  mb->maxlen = maxlen;
  /* we need to allocate one byte more for get_membuf */
  mb->buf = _assuan_malloc (ctx, initiallen + 1);
  if (!mb->buf)
      mb->out_of_core = 1;
}
Ejemplo n.º 2
0
/* Build a command line for use with W32's CreateProcess.  On success
   CMDLINE gets the address of a newly allocated string.  */
static int
build_w32_commandline (assuan_context_t ctx, const char * const *argv,
                       char **cmdline)
{
    int i, n;
    const char *s;
    char *buf, *p;

    *cmdline = NULL;
    n = 0;
    for (i=0; (s = argv[i]); i++)
    {
        n += strlen (s) + 1 + 2;  /* (1 space, 2 quoting */
        for (; *s; s++)
            if (*s == '\"')
                n++;  /* Need to double inner quotes.  */
    }
    n++;

    buf = p = _assuan_malloc (ctx, n);
    if (! buf)
        return -1;

    for (i = 0; argv[i]; i++)
    {
        if (i)
            p = stpcpy (p, " ");
        if (! *argv[i]) /* Empty string. */
            p = stpcpy (p, "\"\"");
        else if (strpbrk (argv[i], " \t\n\v\f\""))
        {
            p = stpcpy (p, "\"");
            for (s = argv[i]; *s; s++)
            {
                *p++ = *s;
                if (*s == '\"')
                    *p++ = *s;
            }
            *p++ = '\"';
            *p = 0;
        }
        else
            p = stpcpy (p, argv[i]);
    }

    *cmdline= buf;
    return 0;
}
Ejemplo n.º 3
0
void *
_assuan_calloc(size_t n, size_t m)
{
    void *p;
    size_t nbytes;

    nbytes = n * m;
    if(m && nbytes / m != n)
    {
        errno = ENOMEM;
        return NULL;
    }

    p = _assuan_malloc(nbytes);
    if(p)
        memset(p, 0, nbytes);
    return p;
}
Ejemplo n.º 4
0
gpg_error_t
assuan_write_status (assuan_context_t ctx,
                     const char *keyword, const char *text)
{
  char buffer[256];
  char *helpbuf;
  size_t n;
  gpg_error_t ae;

  if ( !ctx || !keyword)
    return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
  if (!text)
    text = "";

  n = 2 + strlen (keyword) + 1 + strlen (text) + 1;
  if (n < sizeof (buffer))
    {
      strcpy (buffer, "S ");
      strcat (buffer, keyword);
      if (*text)
        {
          strcat (buffer, " ");
          strcat (buffer, text);
        }
      ae = assuan_write_line (ctx, buffer);
    }
  else if ( (helpbuf = _assuan_malloc (ctx, n)) )
    {
      strcpy (helpbuf, "S ");
      strcat (helpbuf, keyword);
      if (*text)
        {
          strcat (helpbuf, " ");
          strcat (helpbuf, text);
        }
      ae = assuan_write_line (ctx, helpbuf);
      _assuan_free (ctx, helpbuf);
    }
  else
    ae = 0;
  return ae;
}
Ejemplo n.º 5
0
/* Set the text used for the next OK reponse.  This string is
   automatically reset to NULL after the next command. */
gpg_error_t
assuan_set_okay_line (assuan_context_t ctx, const char *line)
{
  if (!ctx)
    return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
  if (!line)
    {
      _assuan_free (ctx, ctx->okay_line);
      ctx->okay_line = NULL;
    }
  else
    {
      /* FIXME: we need to use gcry_is_secure() to test whether
         we should allocate the entire line in secure memory */
      char *buf = _assuan_malloc (ctx, 3 + strlen(line) + 1);
      if (!buf)
        return _assuan_error (ctx, gpg_err_code_from_syserror ());
      strcpy (buf, "OK ");
      strcpy (buf+3, line);
      _assuan_free (ctx, ctx->okay_line);
      ctx->okay_line = buf;
    }
  return 0;
}
Ejemplo n.º 6
0
/* Make a connection to the Unix domain socket NAME and return a new
   Assuan context in CTX.  SERVER_PID is currently not used but may
   become handy in the future.  Defined flag bits are:

     ASSUAN_SOCKET_CONNECT_FDPASSING
        sendmsg and recvmsg are used.

   NAME must either start with a slash and optional with a drive
   prefix ("c:") or use one of these URL schemata:

      file://<fname>

        This is the same as the default just with an explicit schemata.

      assuan://<ipaddr>:<port>
      assuan://[<ip6addr>]:<port>

        Connect using TCP to PORT of the server with the numerical
        IPADDR.  Note that '[' and ']' are literal characters.

  */
gpg_error_t
assuan_socket_connect (assuan_context_t ctx, const char *name,
		       pid_t server_pid, unsigned int flags)
{
  gpg_error_t err = 0;
  assuan_fd_t fd;
#ifdef WITH_IPV6
  struct sockaddr_in6 srvr_addr_in6;
#endif
  struct sockaddr_un srvr_addr_un;
  struct sockaddr_in srvr_addr_in;
  struct sockaddr *srvr_addr = NULL;
  uint16_t port = 0;
  size_t len = 0;
  const char *s;
  int af = AF_LOCAL;
  int pf = PF_LOCAL;

  TRACE2 (ctx, ASSUAN_LOG_CTX, "assuan_socket_connect", ctx,
	  "name=%s, flags=0x%x", name ? name : "(null)", flags);

  if (!ctx || !name)
    return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);

  if (!strncmp (name, "file://", 7) && name[7])
    name += 7;
  else if (!strncmp (name, "assuan://", 9) && name[9])
    {
      name += 9;
      af = AF_INET;
      pf = PF_INET;
    }
  else /* Default.  */
    {
      /* We require that the name starts with a slash if no URL
         schemata is used.  To make things easier we allow an optional
         drive prefix.  */
      s = name;
      if (*s && s[1] == ':')
        s += 2;
      if (*s != DIRSEP_C && *s != '/')
        return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
    }

  if (af == AF_LOCAL)
    {
      if (strlen (name)+1 >= sizeof srvr_addr_un.sun_path)
        return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);

      memset (&srvr_addr_un, 0, sizeof srvr_addr_un);
      srvr_addr_un.sun_family = AF_LOCAL;
      strncpy (srvr_addr_un.sun_path, name, sizeof (srvr_addr_un.sun_path) - 1);
      srvr_addr_un.sun_path[sizeof (srvr_addr_un.sun_path) - 1] = 0;
      len = SUN_LEN (&srvr_addr_un);

      srvr_addr = (struct sockaddr *)&srvr_addr_un;
    }
  else
    {
      char *addrstr, *p;
#ifdef HAVE_INET_PTON
      void *addrbuf = NULL;
#endif

      addrstr = _assuan_malloc (ctx, strlen (name) + 1);
      if (!addrstr)
        return _assuan_error (ctx, gpg_err_code_from_syserror ());

      if (*name == '[')
        {
          strcpy (addrstr, name+1);
          p = strchr (addrstr, ']');
          if (!p || p[1] != ':' || !parse_portno (p+2, &port))
            err = _assuan_error (ctx, GPG_ERR_BAD_URI);
          else
            {
              *p = 0;
#ifdef WITH_IPV6
              af = AF_INET6;
              pf = PF_INET6;
              memset (&srvr_addr_in6, 0, sizeof srvr_addr_in6);
              srvr_addr_in6.sin6_family = af;
              srvr_addr_in6.sin6_port = htons (port);
#ifdef HAVE_INET_PTON
              addrbuf = &srvr_addr_in6.sin6_addr;
#endif
              srvr_addr = (struct sockaddr *)&srvr_addr_in6;
              len = sizeof srvr_addr_in6;
#else
              err =  _assuan_error (ctx, GPG_ERR_EAFNOSUPPORT);
#endif
            }
        }
      else
        {
          strcpy (addrstr, name);
          p = strchr (addrstr, ':');
          if (!p || !parse_portno (p+1, &port))
            err = _assuan_error (ctx, GPG_ERR_BAD_URI);
          else
            {
              *p = 0;
              memset (&srvr_addr_in, 0, sizeof srvr_addr_in);
              srvr_addr_in.sin_family = af;
              srvr_addr_in.sin_port = htons (port);
#ifdef HAVE_INET_PTON
              addrbuf = &srvr_addr_in.sin_addr;
#endif
              srvr_addr = (struct sockaddr *)&srvr_addr_in;
              len = sizeof srvr_addr_in;
            }
        }

      if (!err)
        {
#ifdef HAVE_INET_PTON
          switch (inet_pton (af, addrstr, addrbuf))
            {
            case 1:  break;
            case 0:  err = _assuan_error (ctx, GPG_ERR_BAD_URI); break;
            default: err = _assuan_error (ctx, gpg_err_code_from_syserror ());
            }
#else /*!HAVE_INET_PTON*/
          /* We need to use the old function.  If we are here v6
             support isn't enabled anyway and thus we can do fine
             without.  Note that Windows as a compatible inet_pton
             function named inetPton, but only since Vista.  */
          srvr_addr_in.sin_addr.s_addr = inet_addr (addrstr);
          if (srvr_addr_in.sin_addr.s_addr == INADDR_NONE)
            err = _assuan_error (ctx, GPG_ERR_BAD_URI);
#endif /*!HAVE_INET_PTON*/
        }

      _assuan_free (ctx, addrstr);
      if (err)
        return err;
    }

  fd = _assuan_sock_new (ctx, pf, SOCK_STREAM, 0);
  if (fd == ASSUAN_INVALID_FD)
    {
      err = _assuan_error (ctx, gpg_err_code_from_syserror ());
      TRACE1 (ctx, ASSUAN_LOG_SYSIO, "assuan_socket_connect", ctx,
              "can't create socket: %s", strerror (errno));
      return err;
    }

  if (_assuan_sock_connect (ctx, fd, srvr_addr, len) == -1)
    {
      TRACE2 (ctx, ASSUAN_LOG_SYSIO, "assuan_socket_connect", ctx,
	      "can't connect to `%s': %s\n", name, strerror (errno));
      _assuan_close (ctx, fd);
      return _assuan_error (ctx, GPG_ERR_ASS_CONNECT_FAILED);
    }

  err = _assuan_connect_finalize (ctx, fd, flags);

  if (err)
    _assuan_reset (ctx);

  return err;
}
Ejemplo n.º 7
0
/* This function is similar to pipe_connect but uses a socketpair and
   sets the I/O up to use sendmsg/recvmsg. */
static gpg_error_t
socketpair_connect (assuan_context_t ctx,
                    const char *name, const char **argv,
                    assuan_fd_t *fd_child_list,
                    void (*atfork) (void *opaque, int reserved),
                    void *atforkvalue)
{
  gpg_error_t err;
  int idx;
  int fds[2];
  char mypidstr[50];
  pid_t pid;
  int *child_fds = NULL;
  int child_fds_cnt = 0;
  struct at_socketpair_fork atp;
  int rc;

  TRACE_BEG3 (ctx, ASSUAN_LOG_CTX, "socketpair_connect", ctx,
	      "name=%s,atfork=%p,atforkvalue=%p", name ? name : "(null)",
	      atfork, atforkvalue);

  atp.user_atfork = atfork;
  atp.user_atforkvalue = atforkvalue;
  atp.parent_pid = getpid ();

  if (!ctx
      || (name && (!argv || !argv[0]))
      || (!name && !argv))
    return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);

  if (! ctx->flags.no_fixsignals)
    fix_signals ();

  sprintf (mypidstr, "%lu", (unsigned long)getpid ());

  if (fd_child_list)
    while (fd_child_list[child_fds_cnt] != ASSUAN_INVALID_FD)
      child_fds_cnt++;
  child_fds = _assuan_malloc (ctx, (child_fds_cnt + 2) * sizeof (int));
  if (! child_fds)
    return TRACE_ERR (gpg_err_code_from_syserror ());
  child_fds[1] = ASSUAN_INVALID_FD;
  if (fd_child_list)
    memcpy (&child_fds[1], fd_child_list, (child_fds_cnt + 1) * sizeof (int));

  if (_assuan_socketpair (ctx, AF_LOCAL, SOCK_STREAM, 0, fds))
    {
      TRACE_LOG1 ("socketpair failed: %s", strerror (errno));
      _assuan_free (ctx, child_fds);
      return TRACE_ERR (GPG_ERR_ASS_GENERAL);
    }
  atp.peer_fd = fds[1];
  child_fds[0] = fds[1];

  rc = _assuan_spawn (ctx, &pid, name, argv, ASSUAN_INVALID_FD,
		      ASSUAN_INVALID_FD, child_fds, at_socketpair_fork_cb,
		      &atp, 0);
  if (rc < 0)
    {
      err = gpg_err_code_from_syserror ();
      _assuan_close (ctx, fds[0]);
      _assuan_close (ctx, fds[1]);
      _assuan_free (ctx, child_fds);
      return TRACE_ERR (err);
    }

  /* For W32, the user needs to know the server-local names of the
     inherited handles.  Return them here.  Note that the translation
     of the peer socketpair fd (fd_child_list[0]) must be done by the
     wrapper program based on the environment variable
     _assuan_connection_fd.  */
  if (fd_child_list)
    {
      for (idx = 0; fd_child_list[idx] != -1; idx++)
	/* We add 1 to skip over the socketpair end.  */
	fd_child_list[idx] = child_fds[idx + 1];
    }

  _assuan_free (ctx, child_fds);

  /* If this is the server child process, exit early.  */
  if (! name && (*argv)[0] == 's')
    {
      _assuan_close (ctx, fds[0]);
      return 0;
    }

  _assuan_close (ctx, fds[1]);

  ctx->engine.release = _assuan_client_release;
  ctx->finish_handler = _assuan_client_finish;
  ctx->max_accepts = 1;
  ctx->inbound.fd  = fds[0];
  ctx->outbound.fd = fds[0];
  _assuan_init_uds_io (ctx);

  err = initial_handshake (ctx);
  if (err)
    _assuan_reset (ctx);
  return err;
}
Ejemplo n.º 8
0
/* Build a command line for use with W32's CreateProcess.  On success
   CMDLINE gets the address of a newly allocated string.  */
static int
build_w32_commandline (assuan_context_t ctx, const char * const *argv,
		       assuan_fd_t fd0, assuan_fd_t fd1, assuan_fd_t fd2,
                       int fd2_isnull,
                       char **cmdline)
{
  int i, n;
  const char *s;
  char *buf, *p;
  char fdbuf[3*30];

  p = fdbuf;
  *p = 0;
  if (fd0 != ASSUAN_INVALID_FD)
    {
      snprintf (p, 25, "-&S0=%d ", (int)fd0);
      p += strlen (p);
    }
  if (fd1 != ASSUAN_INVALID_FD)
    {
      snprintf (p, 25, "-&S1=%d ", (int)fd1);
      p += strlen (p);
    }
  if (fd2 != ASSUAN_INVALID_FD)
    {
      if (fd2_isnull)
        strcpy (p, "-&S2=null ");
      else
        snprintf (p, 25, "-&S2=%d ", (int)fd2);
      p += strlen (p);
    }
  
  *cmdline = NULL;
  n = strlen (fdbuf);
  for (i=0; (s = argv[i]); i++)
    {
      if (!i)
        continue; /* Ignore argv[0].  */
      n += strlen (s) + 1 + 2;  /* (1 space, 2 quoting) */
      for (; *s; s++)
        if (*s == '\"')
          n++;  /* Need to double inner quotes.  */
    }
  n++;

  buf = p = _assuan_malloc (ctx, n);
  if (! buf)
    return -1;

  p = stpcpy (p, fdbuf);
  for (i = 0; argv[i]; i++) 
    {
      if (!i)
        continue; /* Ignore argv[0].  */
      if (i > 1)
        p = stpcpy (p, " ");

      if (! *argv[i]) /* Empty string. */
        p = stpcpy (p, "\"\"");
      else if (strpbrk (argv[i], " \t\n\v\f\""))
        {
          p = stpcpy (p, "\"");
          for (s = argv[i]; *s; s++)
            {
              *p++ = *s;
              if (*s == '\"')
                *p++ = *s;
            }
          *p++ = '\"';
          *p = 0;
        }
      else
        p = stpcpy (p, argv[i]);
    }

  *cmdline = buf;
  return 0;
}