Beispiel #1
0
/* Return a malloced string encoded in UTF-8 from the wide char input
   string STRING.  Caller must free this value.  Returns NULL and sets
   ERRNO on failure.  Calling this function with STRING set to NULL is
   not defined.  */
char *
wchar_to_utf8 (const wchar_t *string)
{
  int n;
  char *result;

  n = WideCharToMultiByte (CP_UTF8, 0, string, -1, NULL, 0, NULL, NULL);
  if (n < 0)
    {
      gpg_err_set_errno (EINVAL);
      return NULL;
    }

  result = malloc (n+1);
  if (!result)
    return NULL;

  n = WideCharToMultiByte (CP_UTF8, 0, string, -1, result, n, NULL, NULL);
  if (n < 0)
    {
      free (result);
      gpg_err_set_errno (EINVAL);
      result = NULL;
    }
  return result;
}
Beispiel #2
0
/* Set the current position from where the next read or write starts
   in the data object with the handle DH to OFFSET, relativ to
   WHENCE.  */
gpgme_off_t
gpgme_data_seek (gpgme_data_t dh, gpgme_off_t offset, int whence)
{
  TRACE_BEG2 (DEBUG_DATA, "gpgme_data_seek", dh,
	      "offset=%lli, whence=%i", offset, whence);

  if (!dh)
    {
      gpg_err_set_errno (EINVAL);
      return TRACE_SYSRES (-1);
    }
  if (!dh->cbs->seek)
    {
      gpg_err_set_errno (ENOSYS);
      return TRACE_SYSRES (-1);
    }

  /* For relative movement, we must take into account the actual
     position of the read counter.  */
  if (whence == SEEK_CUR)
    offset -= dh->pending_len;

  offset = (*dh->cbs->seek) (dh, offset, whence);
  if (offset >= 0)
    dh->pending_len = 0;

  return TRACE_SYSRES (offset);
}
Beispiel #3
0
/* Return a malloced wide char string from an UTF-8 encoded input
   string STRING.  Caller must free this value.  Returns NULL and sets
   ERRNO on failure.  Calling this function with STRING set to NULL is
   not defined.  */
wchar_t *
utf8_to_wchar (const char *string)
{
  int n;
  size_t nbytes;
  wchar_t *result;

  n = MultiByteToWideChar (CP_UTF8, 0, string, -1, NULL, 0);
  if (n < 0)
    {
      gpg_err_set_errno (EINVAL);
      return NULL;
    }

  nbytes = (size_t)(n+1) * sizeof(*result);
  if (nbytes / sizeof(*result) != (n+1))
    {
      gpg_err_set_errno (ENOMEM);
      return NULL;
    }
  result = malloc (nbytes);
  if (!result)
    return NULL;

  n = MultiByteToWideChar (CP_UTF8, 0, string, -1, result, n);
  if (n < 0)
    {
      free (result);
      gpg_err_set_errno (EINVAL);
      result = NULL;
    }
  return result;
}
Beispiel #4
0
/* Format NAME which is expected to be in rfc2253 format into a better
   human readable format. Caller must free the returned string.  NULL
   is returned in case of an error.  With TRANSLATE set to true the
   name will be translated to the native encoding.  Note that NAME is
   internally always UTF-8 encoded. */
char *
gpgsm_format_name2 (const char *name, int translate)
{
  estream_t fp;
  struct format_name_cookie cookie;
  es_cookie_io_functions_t io = { NULL };

  memset (&cookie, 0, sizeof cookie);

  io.func_write = format_name_writer;
  fp = es_fopencookie (&cookie, "w", io);
  if (!fp)
    {
      int save_errno = errno;
      log_error ("error creating memory stream: %s\n", strerror (save_errno));
      gpg_err_set_errno (save_errno);
      return NULL;
    }
  gpgsm_es_print_name2 (fp, name, translate);
  es_fclose (fp);
  if (cookie.error || !cookie.buffer)
    {
      xfree (cookie.buffer);
      gpg_err_set_errno (cookie.error);
      return NULL;
    }
  return cookie.buffer;
}
Beispiel #5
0
static ssize_t
__assuan_write (assuan_context_t ctx, assuan_fd_t fd, const void *buffer,
		size_t size)
{
  /* Due to the peculiarities of the W32 API we can't use write for a
     network socket and thus we try to use send first and fallback to
     write if send detects that it is not a network socket.  */
  int res;

  TRACE_BEG3 (ctx, ASSUAN_LOG_SYSIO, "__assuan_write", ctx,
	      "fd=0x%x, buffer=%p, size=%i", fd, buffer, size);

#ifdef HAVE_W32CE_SYSTEM
  /* This is a bit of a hack to support stdout over ssh.  Note that
     fread buffers fully while getchar is line buffered.  Weird, but
     that's the way it is.  ASSUAN_STDIN and ASSUAN_STDOUT are
     special handle values that shouldn't occur in the wild.  */
  if (fd == ASSUAN_STDOUT)
    {
      res = fwrite (buffer, 1, size, stdout);
      return TRACE_SYSRES (res);
    }
#endif

  res = send ((int)fd, buffer, size, 0);
  if (res == -1 && WSAGetLastError () == WSAENOTSOCK)
    {
      DWORD nwrite;

      TRACE_LOG ("send call failed - trying WriteFile");
      res = WriteFile (fd, buffer, size, &nwrite, NULL);
      if (! res)
        {
          TRACE_LOG1 ("WriteFile failed: rc=%d", (int)GetLastError ());
          switch (GetLastError ())
            {
            case ERROR_BROKEN_PIPE: 
            case ERROR_NO_DATA:
	      gpg_err_set_errno (EPIPE);
	      break;

            case ERROR_PIPE_NOT_CONNECTED:
            case ERROR_BUSY:
              gpg_err_set_errno (EAGAIN);
              break;
	      
            default:
	      gpg_err_set_errno (EIO);
	      break;
            }
          res = -1;
        }
      else
        res = (int) nwrite;
    }
  else if (res == -1)
    TRACE_LOG1 ("send call failed: rc=%d", (int)GetLastError ());
  return TRACE_SYSRES (res);
}
Beispiel #6
0
int
_assuan_sock_check_nonce (assuan_context_t ctx, assuan_fd_t fd,
			  assuan_sock_nonce_t *nonce)
{
#ifdef HAVE_W32_SYSTEM
  char buffer[16], *p;
  size_t nleft;
  int n;

  if (sizeof nonce->nonce != 16)
    {
      gpg_err_set_errno (EINVAL);
      return -1;
    }

  if (nonce->length == 42 && nonce->nonce[0] == 42)
    return 0; /* Not a Unix domain socket.  */

  if (nonce->length != 16)
    {
      gpg_err_set_errno (EINVAL);
      return -1;
    }

  p = buffer;
  nleft = 16;
  while (nleft)
    {
      n = _assuan_read (ctx, SOCKET2HANDLE(fd), p, nleft);
      if (n < 0 && errno == EINTR)
        ;
      else if (n < 0 && errno == EAGAIN)
        Sleep (100);
      else if (n < 0)
        return -1;
      else if (!n)
        {
          gpg_err_set_errno (EIO);
          return -1;
        }
      else
        {
          p += n;
          nleft -= n;
        }
    }
  if (memcmp (buffer, nonce->nonce, 16))
    {
      gpg_err_set_errno (EACCES);
      return -1;
    }
#else
  (void)fd;
  (void)nonce;
#endif
  return 0;
}
Beispiel #7
0
/* Close the given file descriptor, created with _assuan_pipe or one
   of the socket functions.  Default implementation.  */
int
__assuan_close (assuan_context_t ctx, assuan_fd_t fd)
{
    int rc = closesocket (HANDLE2SOCKET(fd));
    if (rc)
        gpg_err_set_errno ( _assuan_sock_wsa2errno (WSAGetLastError ()) );
    if (rc && WSAGetLastError () == WSAENOTSOCK)
    {
        rc = CloseHandle (fd);
        if (rc)
            /* FIXME. */
            gpg_err_set_errno (EIO);
    }
    return rc;
}
Beispiel #8
0
static char *
do_bin2hex (const void *buffer, size_t length, char *stringbuf, int with_colon)
{
  const unsigned char *s;
  char *p;

  if (!stringbuf)
    {
      /* Not really correct for with_colon but we don't care about the
         one wasted byte. */
      size_t n = with_colon? 3:2;
      size_t nbytes = n * length + 1;
      if (length &&  (nbytes-1) / n != length)
        {
          gpg_err_set_errno (ENOMEM);
          return NULL;
        }
      stringbuf = xtrymalloc (nbytes);
      if (!stringbuf)
        return NULL;
    }

  for (s = buffer, p = stringbuf; length; length--, s++)
    {
      if (with_colon && s != buffer)
        *p++ = ':';
      *p++ = tohex ((*s>>4)&15);
      *p++ = tohex (*s&15);
    }
  *p = 0;

  return stringbuf;
}
Beispiel #9
0
/* Create pipe where one end is inheritable: With an INHERIT_IDX of 0
   the read end is inheritable, with 1 the write end is inheritable.
   Note that the inheritable ends are rendezvous ids and no file
   descriptors or handles. */
static gpg_error_t
create_inheritable_pipe (int filedes[2], int inherit_idx)
{
  HANDLE hd;
  int rvid;

  filedes[0] = filedes[1] = -1;
  hd = _assuan_w32ce_prepare_pipe (&rvid, !inherit_idx);
  if (hd == INVALID_HANDLE_VALUE)
    {
      log_error ("_assuan_w32ce_prepare_pipe failed: %s\n", w32_strerror (-1));
      gpg_err_set_errno (EIO);
      return gpg_error_from_syserror ();
    }

  if (inherit_idx)
    {
      filedes[0] = handle_to_fd (hd);
      filedes[1] = rvid;
    }
  else
    {
      filedes[0] = rvid;
      filedes[1] = handle_to_fd (hd);
    }
  return 0;
}
Beispiel #10
0
static int
gpgme_error_to_errno (gpgme_error_t err)
{
  int res = gpg_err_code_to_errno (err);

  if (!err)
    {
      switch (gpg_err_code (err))
	{
	case GPG_ERR_EOF:
	  res = 0;
	  break;
	case GPG_ERR_INV_VALUE:
	  res = EINVAL;
	  break;
	case GPG_ERR_NOT_SUPPORTED:
	  res = ENOSYS;
	  break;
	default:
	  /* FIXME: Yeah, well.  */
	  res = EINVAL;
	  break;
	}
    }
  TRACE3 (DEBUG_DATA, "gpgme:gpgme_error_to_errno", 0,
	  "mapping %s <%s> to: %s", gpgme_strerror (err),
	  gpgme_strsource (err), strerror (res));
  gpg_err_set_errno (res);
  return res ? -1 : 0;
}
Beispiel #11
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;
}
Beispiel #12
0
gpgme_error_t
parse_import_res (char *args, gpgme_import_result_t result)
{
  char *tail;

  gpg_err_set_errno (0);

#define PARSE_NEXT(x)					\
  (x) = strtol (args, &tail, 0);			\
  if (errno || args == tail || *tail != ' ')		\
    /* The crypto backend does not behave.  */		\
    return trace_gpg_error (GPG_ERR_INV_ENGINE);        \
  args = tail;

  PARSE_NEXT (result->considered);
  PARSE_NEXT (result->no_user_id);
  PARSE_NEXT (result->imported);
  PARSE_NEXT (result->imported_rsa);
  PARSE_NEXT (result->unchanged);
  PARSE_NEXT (result->new_user_ids);
  PARSE_NEXT (result->new_sub_keys);
  PARSE_NEXT (result->new_signatures);
  PARSE_NEXT (result->new_revocations);
  PARSE_NEXT (result->secret_read);
  PARSE_NEXT (result->secret_imported);
  PARSE_NEXT (result->secret_unchanged);
  PARSE_NEXT (result->skipped_new_keys);
  PARSE_NEXT (result->not_imported);

  return 0;
}
Beispiel #13
0
/* Log the formatted string FORMAT at debug category CAT higher.  */
void
_assuan_debug (assuan_context_t ctx, unsigned int cat, const char *format, ...)
{
  va_list arg_ptr;
  int saved_errno;
  char *msg;
  int res;

  /* vasprintf is an expensive operation thus we first check whether
     the callback has enabled CAT for logging.  */
  if (!ctx
      || !ctx->log_cb
      || !(*ctx->log_cb) (ctx, ctx->log_cb_data, cat, NULL))
    return;

  saved_errno = errno;
  va_start (arg_ptr, format);
  res = gpgrt_vasprintf (&msg, format, arg_ptr);
  va_end (arg_ptr);
  if (res < 0)
    return;
  ctx->log_cb (ctx, ctx->log_cb_data, cat, msg);
  free (msg);
  gpg_err_set_errno (saved_errno);
}
Beispiel #14
0
static int
get_err_from_number (char *str, gpg_error_t *err)
{
  unsigned long nr;
  char *tail;

  gpg_err_set_errno (0);
  nr = strtoul (str, &tail, 0);
  if (errno)
    return 0;

  if (nr > UINT_MAX)
    return 0;

  if (*tail)
    {
      unsigned long cnr = strtoul (tail + 1, &tail, 0);
      if (errno || *tail)
	return 0;

      if (nr >= GPG_ERR_SOURCE_DIM || cnr >= GPG_ERR_CODE_DIM)
	return 0;

      nr = gpg_err_make (nr, cnr);
    }

  *err = (unsigned int) nr;
  return 1;
}
Beispiel #15
0
static time_t
_gpgme_timegm (struct tm *tm)
{
  /* This one is thread safe.  */
  SYSTEMTIME st;
  FILETIME ft;
  unsigned long long cnsecs;

  st.wYear   = tm->tm_year + 1900;
  st.wMonth  = tm->tm_mon  + 1;
  st.wDay    = tm->tm_mday;
  st.wHour   = tm->tm_hour;
  st.wMinute = tm->tm_min;
  st.wSecond = tm->tm_sec;
  st.wMilliseconds = 0; /* Not available.  */
  st.wDayOfWeek = 0;    /* Ignored.  */

  /* System time is UTC thus the conversion is pretty easy.  */
  if (!SystemTimeToFileTime (&st, &ft))
    {
      gpg_err_set_errno (EINVAL);
      return (time_t)(-1);
    }

  cnsecs = (((unsigned long long)ft.dwHighDateTime << 32)
	    | ft.dwLowDateTime);
  cnsecs -= 116444736000000000ULL; /* The filetime epoch is 1601-01-01.  */
  return (time_t)(cnsecs / 10000000ULL);
}
Beispiel #16
0
int
_assuan_sock_get_nonce (assuan_context_t ctx, struct sockaddr *addr,
			int addrlen, assuan_sock_nonce_t *nonce)
{
#ifdef HAVE_W32_SYSTEM
  if (addr->sa_family == AF_LOCAL || addr->sa_family == AF_UNIX)
    {
      struct sockaddr_un *unaddr;
      unsigned short port;

      if (sizeof nonce->nonce != 16)
        {
          gpg_err_set_errno (EINVAL);
          return -1;
        }
      nonce->length = 16;
      unaddr = (struct sockaddr_un *)addr;
      if (read_port_and_nonce (unaddr->sun_path, &port, nonce->nonce))
        return -1;
    }
  else
    {
      nonce->length = 42; /* Arbitrary value to detect unitialized nonce. */
      nonce->nonce[0] = 42;
    }
#else
  (void)addr;
  (void)addrlen;
  nonce->length = 0;
#endif
  return 0;
}
Beispiel #17
0
/*
 * Try to open a file without the extension ".sig" or ".asc"
 * Return NULL if such a file is not available.
 */
iobuf_t
open_sigfile (const char *sigfilename, progress_filter_context_t *pfx)
{
  iobuf_t a = NULL;
  char *buf;

  buf = get_matching_datafile (sigfilename);
  if (buf)
    {
      a = iobuf_open (buf);
      if (a && is_secured_file (iobuf_get_fd (a)))
        {
          iobuf_close (a);
          a = NULL;
          gpg_err_set_errno (EPERM);
        }
      if (a)
        log_info (_("assuming signed data in '%s'\n"), buf);
      if (a && pfx)
        handle_progress (pfx, a, buf);
      xfree (buf);
    }

  return a;
}
Beispiel #18
0
int
__assuan_sendmsg (assuan_context_t ctx, assuan_fd_t fd, assuan_msghdr_t msg,
                  int flags)
{
    gpg_err_set_errno (ENOSYS);
    return -1;
}
/* Close all file descriptors starting with descriptor FIRST.  If
   EXCEPT is not NULL, it is expected to be a list of file descriptors
   which shall not be closed.  This list shall be sorted in ascending
   order with the end marked by -1.  */
void
close_all_fds (int first, int *except)
{
    int max_fd = get_max_fds ();
    int fd, i, except_start;

    if (except)
    {
        except_start = 0;
        for (fd=first; fd < max_fd; fd++)
        {
            for (i=except_start; except[i] != -1; i++)
            {
                if (except[i] == fd)
                {
                    /* If we found the descriptor in the exception list
                       we can start the next compare run at the next
                       index because the exception list is ordered.  */
                    except_start = i + 1;
                    break;
                }
            }
            if (except[i] == -1)
                close (fd);
        }
    }
    else
    {
        for (fd=first; fd < max_fd; fd++)
            close (fd);
    }

    gpg_err_set_errno (0);
}
Beispiel #20
0
/* Write to the domain server.  */
static ssize_t
uds_writer (assuan_context_t ctx, const void *buf, size_t buflen)
{
#ifndef HAVE_W32_SYSTEM
  struct msghdr msg;
  struct iovec iovec;
  ssize_t len;

  memset (&msg, 0, sizeof (msg));

  msg.msg_name = NULL;
  msg.msg_namelen = 0;
  msg.msg_iovlen = 1;
  msg.msg_iov = &iovec;
  iovec.iov_base = (void*)buf;
  iovec.iov_len = buflen;

  len = _assuan_sendmsg (ctx, ctx->outbound.fd, &msg, 0);

  return len;
#else /*HAVE_W32_SYSTEM*/
  int res = sendto (HANDLE2SOCKET(ctx->outbound.fd), buf, buflen, 0,
		    (struct sockaddr *)&ctx->serveraddr,
		    sizeof (struct sockaddr_in));
  if (res < 0)
    gpg_err_set_errno ( _assuan_sock_wsa2errno (WSAGetLastError ()));
  return res;
#endif /*HAVE_W32_SYSTEM*/
}
Beispiel #21
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;
}
Beispiel #22
0
/* The writer function for the memory stream. */
static ssize_t
format_name_writer (void *cookie, const void *buffer, size_t size)
{
  struct format_name_cookie *c = cookie;
  char *p;

  if (!c->buffer)
    {
      p = xtrymalloc (size + 1 + 1);
      if (p)
        {
          c->size = size + 1;
          c->buffer = p;
          c->len = 0;
        }
    }
  else if (c->len + size < c->len)
    {
      p = NULL;
      gpg_err_set_errno (ENOMEM);
    }
  else if (c->size < c->len + size)
    {
      p = xtryrealloc (c->buffer, c->len + size + 1);
      if (p)
        {
          c->size = c->len + size;
          c->buffer = p;
        }
    }
  else
    p = c->buffer;
  if (!p)
    {
      c->error = errno;
      xfree (c->buffer);
      c->buffer = NULL;
      gpg_err_set_errno (c->error);
      return -1;
    }
  memcpy (p + c->len, buffer, size);
  c->len += size;
  p[c->len] = 0; /* Terminate string. */

  return (ssize_t)size;
}
Beispiel #23
0
/* W32: Fill BUFFER with LENGTH bytes of random.  Returns -1 on
   failure, 0 on success.  Sets errno on failure.  */
static int
get_nonce (char *buffer, size_t nbytes) 
{
  HCRYPTPROV prov;
  int ret = -1;

  if (!CryptAcquireContext (&prov, NULL, NULL, PROV_RSA_FULL, 
                            (CRYPT_VERIFYCONTEXT|CRYPT_SILENT)) )
    gpg_err_set_errno (ENODEV);
  else 
    {
      if (!CryptGenRandom (prov, nbytes, (unsigned char *) buffer))
        gpg_err_set_errno (ENODEV);
      else
        ret = 0;
      CryptReleaseContext (prov, 0);
    }
  return ret;
}
Beispiel #24
0
/* Close the given file descriptor, created with _assuan_pipe or one
   of the socket functions.  Default implementation.  */
int
__assuan_close (assuan_context_t ctx, assuan_fd_t fd)
{
  int rc = closesocket (HANDLE2SOCKET(fd));
  int err = WSAGetLastError ();

  /* Note that gpg_err_set_errno on Windows CE overwrites
     WSAGetLastError() (via SetLastError()).  */
  if (rc)
    gpg_err_set_errno (_assuan_sock_wsa2errno (err));
  if (rc && err == WSAENOTSOCK)
    {
      rc = CloseHandle (fd);
      if (rc)
        /* FIXME. */
        gpg_err_set_errno (EIO);
    }
  return rc;
}
Beispiel #25
0
static int
my_sendmsg (assuan_context_t ctx, assuan_fd_t fd, const assuan_msghdr_t msg,
	    int flags)
{
#ifdef HAVE_W32_SYSTEM
  gpg_err_set_errno (ENOSYS);
  return -1;
#else
  return _gpgme_io_sendmsg ((int) fd, msg, flags);
#endif
}
Beispiel #26
0
static gpgme_ssize_t
user_read (gpgme_data_t dh, void *buffer, size_t size)
{
  if (!dh->data.user.cbs->read)
    {
      gpg_err_set_errno (EBADF);
      return -1;
    }

  return (*dh->data.user.cbs->read) (dh->data.user.handle, buffer, size);
}
Beispiel #27
0
static gpgme_off_t
user_seek (gpgme_data_t dh, gpgme_off_t offset, int whence)
{
  if (!dh->data.user.cbs->seek)
    {
      gpg_err_set_errno (EBADF);
      return -1;
    }

  return (*dh->data.user.cbs->seek) (dh->data.user.handle, offset, whence);
}
Beispiel #28
0
static gpgme_ssize_t
user_write (gpgme_data_t dh, const void *buffer, size_t size)
{
  if (!dh->data.user.cbs->write)
    {
      gpg_err_set_errno (EBADF);
      return -1;
    }

  return (*dh->data.user.cbs->write) (dh->data.user.handle, buffer, size);
}
Beispiel #29
0
/* Convert HEXSTRING consisting of hex characters into string and
   store that at BUFFER.  HEXSTRING is either delimited by end of
   string or a white space character.  The function makes sure that
   the resulting string in BUFFER is terminated by a Nul byte.  Note
   that the retruned string may include embedded Nul bytes; the extra
   Nul byte at the end is used to make sure tha the result can always
   be used as a C-string.

   BUFSIZE is the available length of BUFFER; if the converted result
   plus a possible required extra Nul character does not fit into this
   buffer, the function returns NULL and won't change the existing
   content of BUFFER.  In-place conversion is possible as long as
   BUFFER points to HEXSTRING.

   If BUFFER is NULL and BUFSIZE is 0 the function scans HEXSTRING but
   does not store anything.  This may be used to find the end of
   HEXSTRING.

   On success the function returns a pointer to the next character
   after HEXSTRING (which is either end-of-string or a the next white
   space).  If BUFLEN is not NULL the number of valid vytes in BUFFER
   is stored there (an extra Nul byte is not counted); this will even
   be done if BUFFER has been passed as NULL. */
const char *
hex2str (const char *hexstring, char *buffer, size_t bufsize, size_t *buflen)
{
  const char *s = hexstring;
  int idx, count;
  int need_nul = 0;

  if (buflen)
    *buflen = 0;

  for (s=hexstring, count=0; hexdigitp (s) && hexdigitp (s+1); s += 2, count++)
    ;
  if (*s && (!isascii (*s) || !isspace (*s)) )
    {
      gpg_err_set_errno (EINVAL);
      return NULL;   /* Not followed by Nul or white space.  */
    }
  /* We need to append a nul character.  However we don't want that if
     the hexstring already ends with "00".  */
  need_nul = ((s == hexstring) || !(s[-2] == '0' && s[-1] == '0'));
  if (need_nul)
    count++;

  if (buffer)
    {
      if (count > bufsize)
        {
          gpg_err_set_errno (EINVAL);
          return NULL; /* Too long.  */
        }

      for (s=hexstring, idx=0; hexdigitp (s) && hexdigitp (s+1); s += 2)
        ((unsigned char*)buffer)[idx++] = xtoi_2 (s);
      if (need_nul)
        buffer[idx] = 0;
    }

  if (buflen)
    *buflen = count - need_nul;
  return s;
}
Beispiel #30
0
static gpgme_error_t
parse_enc_to (char *args, gpgme_recipient_t *recp, gpgme_protocol_t protocol)
{
  gpgme_recipient_t rec;
  char *tail;
  int i;

  rec = malloc (sizeof (*rec));
  if (!rec)
    return gpg_error_from_syserror ();

  rec->next = NULL;
  rec->keyid = rec->_keyid;
  rec->status = 0;

  for (i = 0; i < sizeof (rec->_keyid) - 1; i++)
    {
      if (args[i] == '\0' || args[i] == ' ')
	break;

      rec->_keyid[i] = args[i];
    }
  rec->_keyid[i] = '\0';

  args = &args[i];
  if (*args != '\0' && *args != ' ')
    {
      free (rec);
      return trace_gpg_error (GPG_ERR_INV_ENGINE);
    }

  while (*args == ' ')
    args++;

  if (*args)
    {
      gpg_err_set_errno (0);
      rec->pubkey_algo = _gpgme_map_pk_algo (strtol (args, &tail, 0), protocol);
      if (errno || args == tail || *tail != ' ')
	{
	  /* The crypto backend does not behave.  */
	  free (rec);
	  return trace_gpg_error (GPG_ERR_INV_ENGINE);
	}
    }

  /* FIXME: The key length is always 0 right now, so no need to parse
     it.  */

  *recp = rec;
  return 0;
}