Ejemplo n.º 1
0
static gpg_error_t
process_request (assuan_context_t ctx)
{
  gpg_error_t rc;

  if (ctx->in_inquire)
    return _assuan_error (ctx, GPG_ERR_ASS_NESTED_COMMANDS);

  do
    {
      rc = _assuan_read_line (ctx);
    }
  while (_assuan_error_is_eagain (ctx, rc));
  if (gpg_err_code (rc) == GPG_ERR_EOF)
    {
      ctx->process_complete = 1;
      return 0;
    }
  if (rc)
    return rc;
  if (*ctx->inbound.line == '#' || !ctx->inbound.linelen)
    return 0; /* comment line - ignore */

  ctx->in_command = 1;
  ctx->outbound.data.error = 0;
  ctx->outbound.data.linelen = 0;
  /* dispatch command and return reply */
  rc = dispatch_command (ctx, ctx->inbound.line, ctx->inbound.linelen);

  return assuan_process_done (ctx, rc);
}
Ejemplo n.º 2
0
static gpg_error_t
process_next (assuan_context_t ctx)
{
  gpg_error_t rc;

  /* What the next thing to do is depends on the current state.
     However, we will always first read the next line.  The client is
     required to write full lines without blocking long after starting
     a partial line.  */
  rc = _assuan_read_line (ctx);
  if (_assuan_error_is_eagain (ctx, rc))
    return 0;
  if (gpg_err_code (rc) == GPG_ERR_EOF)
    {
      ctx->process_complete = 1;
      return 0;
    }
  if (rc)
    return rc;
  if (*ctx->inbound.line == '#' || !ctx->inbound.linelen)
     /* Comment lines are ignored.  */
    return 0;

  /* Now we have a line that really means something.  It could be one
     of the following things: First, if we are not in a command
     already, it is the next command to dispatch.  Second, if we are
     in a command, it can only be the response to an INQUIRE
     reply.  */

  if (!ctx->in_command)
    {
      ctx->in_command = 1;

      ctx->outbound.data.error = 0;
      ctx->outbound.data.linelen = 0;
      /* Dispatch command and return reply.  */
      ctx->in_process_next = 1;
      rc = dispatch_command (ctx, ctx->inbound.line, ctx->inbound.linelen);
      ctx->in_process_next = 0;
    }
  else if (ctx->in_inquire)
    {
      /* FIXME: Pick up the continuation.  */
      rc = _assuan_inquire_ext_cb (ctx);
    }
  else
    {
      /* Should not happen.  The client is sending data while we are
	 in a command and not waiting for an inquire.  We log an error
	 and discard it.  */
      TRACE0 (ctx, ASSUAN_LOG_DATA, "process_next", ctx,
	      "unexpected client data");
      rc = 0;
    }

  return rc;
}
Ejemplo n.º 3
0
/* This function also does deescaping for data lines.  */
gpg_error_t
assuan_client_read_response (assuan_context_t ctx,
			     char **line_r, int *linelen_r)
{
  gpg_error_t rc;
  char *line = NULL;
  int linelen = 0;

  *line_r = NULL;
  *linelen_r = 0;

  do 
    {
      do
	{
	  rc = _assuan_read_line (ctx);
	}
      while (_assuan_error_is_eagain (ctx, rc));
      if (rc)
        return rc;
      line = ctx->inbound.line;
      linelen = ctx->inbound.linelen;
    }    
  while (!linelen);

  /* For data lines, we deescape immediately.  The user will never
     have to worry about it.  */
  if (linelen >= 1 && line[0] == 'D' && line[1] == ' ')
    {
      char *s, *d;
      for (s=d=line; linelen; linelen--)
	{
	  if (*s == '%' && linelen > 2)
	    { /* handle escaping */
	      s++;
	      *d++ = xtoi_2 (s);
	      s += 2;
	      linelen -= 2;
	    }
	  else
	    *d++ = *s++;
	}
      *d = 0; /* add a hidden string terminator */

      linelen = d - line;
      ctx->inbound.linelen = linelen;
    }

  *line_r = line;
  *linelen_r = linelen;

  return 0;
}
/* Read the next line from the client or server and return a pointer
   in *LINE to a buffer holding the line.  LINELEN is the length of
   *LINE.  The buffer is valid until the next read operation on it.
   The caller may modify the buffer.  The buffer is invalid (i.e. must
   not be used) if an error is returned.

   Returns 0 on success or an assuan error code.
   See also: assuan_pending_line().
*/
assuan_error_t
assuan_read_line (assuan_context_t ctx, char **line, size_t *linelen)
{
  assuan_error_t err;

  if (!ctx)
    return ASSUAN_Invalid_Value;

  err = _assuan_read_line (ctx);
  *line = ctx->inbound.line;
  *linelen = ctx->inbound.linelen;
  return err;
}
Ejemplo n.º 5
0
/* Read the next line from the client or server and return a pointer
   in *LINE to a buffer holding the line.  LINELEN is the length of
   *LINE.  The buffer is valid until the next read operation on it.
   The caller may modify the buffer.  The buffer is invalid (i.e. must
   not be used) if an error is returned.

   Returns 0 on success or an assuan error code.
   See also: assuan_pending_line().
*/
gpg_error_t
assuan_read_line (assuan_context_t ctx, char **line, size_t *linelen)
{
  gpg_error_t err;

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

  do
    {
      err = _assuan_read_line (ctx);
    }
  while (_assuan_error_is_eagain (ctx, err));

  *line = ctx->inbound.line;
  *linelen = ctx->inbound.linelen;

  return err;
}
Ejemplo n.º 6
0
/**
 * assuan_inquire:
 * @ctx: An assuan context
 * @keyword: The keyword used for the inquire
 * @r_buffer: Returns an allocated buffer
 * @r_length: Returns the length of this buffer
 * @maxlen: If not 0, the size limit of the inquired data.
 * 
 * A Server may use this to Send an inquire.  r_buffer, r_length and
 * maxlen may all be NULL/0 to indicate that no real data is expected.
 * 
 * Return value: 0 on success or an ASSUAN error code
 **/
assuan_error_t
assuan_inquire (assuan_context_t ctx, const char *keyword,
                unsigned char **r_buffer, size_t *r_length, size_t maxlen)
{
  assuan_error_t rc;
  struct membuf mb;
  char cmdbuf[LINELENGTH-10]; /* (10 = strlen ("INQUIRE ")+CR,LF) */
  unsigned char *line, *p;
  int linelen;
  int nodataexpected;

  if (!ctx || !keyword || (10 + strlen (keyword) >= sizeof (cmdbuf)))
    return _assuan_error (ASSUAN_Invalid_Value);
  nodataexpected = !r_buffer && !r_length && !maxlen;
  if (!nodataexpected && (!r_buffer || !r_length))
    return _assuan_error (ASSUAN_Invalid_Value);
  if (!ctx->is_server)
    return _assuan_error (ASSUAN_Not_A_Server);
  if (ctx->in_inquire)
    return _assuan_error (ASSUAN_Nested_Commands);
  
  ctx->in_inquire = 1;
  if (nodataexpected)
    memset (&mb, 0, sizeof mb); /* avoid compiler warnings */
  else
    init_membuf (&mb, maxlen? maxlen:1024, maxlen);

  strcpy (stpcpy (cmdbuf, "INQUIRE "), keyword);
  rc = assuan_write_line (ctx, cmdbuf);
  if (rc)
    goto leave;

  for (;;)
    {
      do 
        {
	  do
	    rc = _assuan_read_line (ctx);
	  while (_assuan_error_is_eagain (rc));
          if (rc)
            goto leave;
          line = (unsigned char *) ctx->inbound.line;
          linelen = ctx->inbound.linelen;
        }    
      while (*line == '#' || !linelen);
      if (line[0] == 'E' && line[1] == 'N' && line[2] == 'D'
          && (!line[3] || line[3] == ' '))
        break; /* END command received*/
      if (line[0] == 'C' && line[1] == 'A' && line[2] == 'N')
        {
          rc = _assuan_error (ASSUAN_Canceled);
          goto leave;
        }
      if (line[0] != 'D' || line[1] != ' ' || nodataexpected)
        {
          rc = _assuan_error (ASSUAN_Unexpected_Command);
          goto leave;
        }
      if (linelen < 3)
        continue;
      line += 2;
      linelen -= 2;

      p = line;
      while (linelen)
        {
          for (;linelen && *p != '%'; linelen--, p++)
            ;
          put_membuf (&mb, line, p-line);
          if (linelen > 2)
            { /* handle escaping */
              unsigned char tmp[1];
              p++;
              *tmp = xtoi_2 (p);
              p += 2;
              linelen -= 3;
              put_membuf (&mb, tmp, 1);
            }
          line = p;
        }
      if (mb.too_large)
        {
          rc = _assuan_error (ASSUAN_Too_Much_Data);
          goto leave;
        }
    }

  if (!nodataexpected)
    {
      *r_buffer = get_membuf (&mb, r_length);
      if (!*r_buffer)
        rc = _assuan_error (ASSUAN_Out_Of_Core);
    }

 leave:
  if (!nodataexpected)
    free_membuf (&mb);
  ctx->in_inquire = 0;
  return rc;
}
Ejemplo n.º 7
0
/**
 * assuan_inquire:
 * @ctx: An assuan context
 * @keyword: The keyword used for the inquire
 * @r_buffer: Returns an allocated buffer
 * @r_length: Returns the length of this buffer
 * @maxlen: If not 0, the size limit of the inquired data.
 * 
 * A Server may use this to Send an inquire.  r_buffer, r_length and
 * maxlen may all be NULL/0 to indicate that no real data is expected.
 * 
 * Return value: 0 on success or an ASSUAN error code
 **/
gpg_error_t
assuan_inquire (assuan_context_t ctx, const char *keyword,
                unsigned char **r_buffer, size_t *r_length, size_t maxlen)
{
  gpg_error_t rc;
  struct membuf mb;
  char cmdbuf[LINELENGTH-10]; /* (10 = strlen ("INQUIRE ")+CR,LF) */
  unsigned char *line, *p;
  int linelen;
  int nodataexpected;

  if (!ctx || !keyword || (10 + strlen (keyword) >= sizeof (cmdbuf)))
    return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
  nodataexpected = !r_buffer && !r_length && !maxlen;
  if (!nodataexpected && (!r_buffer || !r_length))
    return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
  if (!ctx->is_server)
    return _assuan_error (ctx, GPG_ERR_ASS_NOT_A_SERVER);
  if (ctx->in_inquire)
    return _assuan_error (ctx, GPG_ERR_ASS_NESTED_COMMANDS);
  
  ctx->in_inquire = 1;
  if (nodataexpected)
    memset (&mb, 0, sizeof mb); /* avoid compiler warnings */
  else
    init_membuf (ctx, &mb, maxlen? maxlen:1024, maxlen);

  strcpy (stpcpy (cmdbuf, "INQUIRE "), keyword);
  rc = assuan_write_line (ctx, cmdbuf);
  if (rc)
    goto leave;

  for (;;)
    {
      do 
        {
	  do
	    rc = _assuan_read_line (ctx);
	  while (_assuan_error_is_eagain (ctx, rc));
          if (rc)
            goto leave;
          line = (unsigned char *) ctx->inbound.line;
          linelen = ctx->inbound.linelen;
        }    
      while (*line == '#' || !linelen);
      if (line[0] == 'E' && line[1] == 'N' && line[2] == 'D'
          && (!line[3] || line[3] == ' '))
        break; /* END command received*/
      if (line[0] == 'C' && line[1] == 'A' && line[2] == 'N')
        {
          rc = _assuan_error (ctx, GPG_ERR_ASS_CANCELED);
          goto leave;
        }
      if (line[0] != 'D' || line[1] != ' ' || nodataexpected)
        {
          rc = _assuan_error (ctx, GPG_ERR_ASS_UNEXPECTED_CMD);
          goto leave;
        }
      if (linelen < 3)
        continue;
      line += 2;
      linelen -= 2;

      p = line;
      while (linelen)
        {
          for (;linelen && *p != '%'; linelen--, p++)
            ;
          put_membuf (ctx, &mb, line, p-line);
          if (linelen > 2)
            { /* handle escaping */
              unsigned char tmp[1];
              p++;
              *tmp = xtoi_2 (p);
              p += 2;
              linelen -= 3;
              put_membuf (ctx, &mb, tmp, 1);
            }
          line = p;
        }
      if (mb.too_large)
        {
          rc = _assuan_error (ctx, GPG_ERR_ASS_TOO_MUCH_DATA);
          goto leave;
        }
    }

  if (!nodataexpected)
    {
      *r_buffer = get_membuf (ctx, &mb, r_length);
      if (!*r_buffer)
	rc = _assuan_error (ctx, gpg_err_code_from_syserror ());
    }

 leave:
  if (!nodataexpected)
    free_membuf (ctx, &mb);
  ctx->in_inquire = 0;
  return rc;
}
assuan_error_t
_assuan_read_from_server (assuan_context_t ctx, int *okay, int *off)
{
  char *line;
  int linelen;
  assuan_error_t rc;

  *okay = 0;
  *off = 0;
  do 
    {
      rc = _assuan_read_line (ctx);
      if (rc)
        return rc;
      line = ctx->inbound.line;
      linelen = ctx->inbound.linelen;
    }    
  while (*line == '#' || !linelen);

  if (linelen >= 1
      && line[0] == 'D' && line[1] == ' ')
    {
      *okay = 2; /* data line */
      *off = 2;
    }
  else if (linelen >= 1
           && line[0] == 'S' 
           && (line[1] == '\0' || line[1] == ' '))
    {
      *okay = 4;
      *off = 1;
      while (line[*off] == ' ')
        ++*off;
    }  
  else if (linelen >= 2
           && line[0] == 'O' && line[1] == 'K'
           && (line[2] == '\0' || line[2] == ' '))
    {
      *okay = 1;
      *off = 2;
      while (line[*off] == ' ')
        ++*off;
    }
  else if (linelen >= 3
           && line[0] == 'E' && line[1] == 'R' && line[2] == 'R'
           && (line[3] == '\0' || line[3] == ' '))
    {
      *okay = 0;
      *off = 3;
      while (line[*off] == ' ')
        ++*off;
    }  
  else if (linelen >= 7
           && line[0] == 'I' && line[1] == 'N' && line[2] == 'Q'
           && line[3] == 'U' && line[4] == 'I' && line[5] == 'R'
           && line[6] == 'E' 
           && (line[7] == '\0' || line[7] == ' '))
    {
      *okay = 3;
      *off = 7;
      while (line[*off] == ' ')
        ++*off;
    }
  else if (linelen >= 3
           && line[0] == 'E' && line[1] == 'N' && line[2] == 'D'
           && (line[3] == '\0' || line[3] == ' '))
    {
      *okay = 5; /* end line */
      *off = 3;
    }
  else
    rc = ASSUAN_Invalid_Response;
  return rc;
}