예제 #1
0
파일: gpgme.c 프로젝트: danielmelogpi/gpgme
/* Add the human-readable notation data with name NAME and value VALUE
   to the context CTX, using the flags FLAGS.  If NAME is NULL, then
   VALUE should be a policy URL.  The flag
   GPGME_SIG_NOTATION_HUMAN_READABLE is forced to be true for notation
   data, and false for policy URLs.  */
gpgme_error_t
gpgme_sig_notation_add (gpgme_ctx_t ctx, const char *name,
			const char *value, gpgme_sig_notation_flags_t flags)
{
  gpgme_error_t err;
  gpgme_sig_notation_t notation;
  gpgme_sig_notation_t *lastp;

  TRACE_BEG3 (DEBUG_CTX, "gpgme_sig_notation_add", ctx,
	      "name=%s, value=%s, flags=0x%x",
	      name ? name : "(null)", value ? value : "(null)",
	      flags);

  if (!ctx)
    return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));

  if (name)
    flags |= GPGME_SIG_NOTATION_HUMAN_READABLE;
  else
    flags &= ~GPGME_SIG_NOTATION_HUMAN_READABLE;

  err = _gpgme_sig_notation_create (&notation, name, name ? strlen (name) : 0,
				    value, value ? strlen (value) : 0, flags);
  if (err)
    return TRACE_ERR (err);

  lastp = &ctx->sig_notations;
  while (*lastp)
    lastp = &(*lastp)->next;

  *lastp = notation;
  return TRACE_ERR (0);
}
예제 #2
0
gpgme_error_t
gpgme_op_vfs_create (gpgme_ctx_t ctx, gpgme_key_t recp[],
		      const char *container_file, unsigned int flags,
		      gpgme_error_t *op_err)
{
  gpg_error_t err;

  TRACE_BEG3 (DEBUG_CTX, "gpgme_op_vfs_create", ctx,
	      "container_file=%s, flags=0x%x, op_err=%p",
	      container_file, flags, op_err);

  if (!ctx)
    return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));

  if (_gpgme_debug_trace () && recp)
    {
      int i = 0;
      
      while (recp[i])
	{
	  TRACE_LOG3 ("recipient[%i] = %p (%s)", i, recp[i],
		      (recp[i]->subkeys && recp[i]->subkeys->fpr) ? 
		      recp[i]->subkeys->fpr : "invalid");
	  i++;
	}
    }

  err = _gpgme_op_vfs_create (ctx, recp, container_file, flags, op_err);
  return TRACE_ERR (err);
}
예제 #3
0
/* Encrypt plaintext PLAIN within CTX for the recipients RECP and
   store the resulting ciphertext in CIPHER.  Also sign the ciphertext
   with the signers in CTX.  */
gpgme_error_t
gpgme_op_encrypt_sign_start (gpgme_ctx_t ctx, gpgme_key_t recp[],
			     gpgme_encrypt_flags_t flags,
			     gpgme_data_t plain, gpgme_data_t cipher)
{
  gpgme_error_t err;

  TRACE_BEG3 (DEBUG_CTX, "gpgme_op_encrypt_sign_start", ctx,
	      "flags=0x%x, plain=%p, cipher=%p", flags, plain, cipher);

  if (!ctx)
    return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
  
  if (_gpgme_debug_trace () && recp)
    {
      int i = 0;

      while (recp[i])
	{
	  TRACE_LOG3 ("recipient[%i] = %p (%s)", i, recp[i],
		      (recp[i]->subkeys && recp[i]->subkeys->fpr) ? 
		      recp[i]->subkeys->fpr : "invalid");
	  i++;
	}
    }

  err = encrypt_sign_start (ctx, 0, recp, flags, plain, cipher);
  return err;
}
예제 #4
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);
}
예제 #5
0
파일: export.c 프로젝트: nobled/gpgme
/* Export the keys listed in PATTERN into KEYDATA.  */
gpgme_error_t
gpgme_op_export_start (gpgme_ctx_t ctx, const char *pattern,
		       gpgme_export_mode_t mode, gpgme_data_t keydata)
{
  gpgme_error_t err;

  TRACE_BEG3 (DEBUG_CTX, "gpgme_op_export_start", ctx,
	      "pattern=%s, mode=0x%x, keydata=%p", pattern, mode, keydata);
  err = export_start (ctx, 0, pattern, mode, keydata);
  return TRACE_ERR (err);
}
예제 #6
0
파일: verify.c 프로젝트: nobled/gpgme
/* Decrypt ciphertext CIPHER and make a signature verification within
   CTX and store the resulting plaintext in PLAIN.  */
gpgme_error_t
gpgme_op_verify_start (gpgme_ctx_t ctx, gpgme_data_t sig,
		       gpgme_data_t signed_text, gpgme_data_t plaintext)
{
  gpg_error_t err;
  TRACE_BEG3 (DEBUG_CTX, "gpgme_op_verify_start", ctx,
	      "sig=%p, signed_text=%p, plaintext=%p",
	      sig, signed_text, plaintext);
  err = verify_start (ctx, 0, sig, signed_text, plaintext);
  return TRACE_ERR (err);
}
예제 #7
0
파일: delete.c 프로젝트: nobled/gpgme
/* Delete KEY from the keyring.  If ALLOW_SECRET is non-zero, secret
   keys are also deleted.  */
gpgme_error_t
gpgme_op_delete_start (gpgme_ctx_t ctx, const gpgme_key_t key,
		       int allow_secret)
{
  gpgme_error_t err;

  TRACE_BEG3 (DEBUG_CTX, "gpgme_op_delete", ctx,
	      "key=%p (%s), allow_secret=%i", key,
	      (key->subkeys && key->subkeys->fpr) ? 
	      key->subkeys->fpr : "invalid", allow_secret);
  err = delete_start (ctx, 0, key, allow_secret);
  return TRACE_ERR (err);
}
예제 #8
0
파일: export.c 프로젝트: nobled/gpgme
/* Export the keys listed in PATTERN into KEYDATA.  */
gpgme_error_t
gpgme_op_export (gpgme_ctx_t ctx, const char *pattern,
		 gpgme_export_mode_t mode, gpgme_data_t keydata)
{
  gpgme_error_t err;

  TRACE_BEG3 (DEBUG_CTX, "gpgme_op_export", ctx,
	      "pattern=%s, mode=0x%x, keydata=%p", pattern, mode, keydata);

  err = export_start (ctx, 1, pattern, mode, keydata);
  if (!err)
    err = _gpgme_wait_one (ctx);
  return err;
}
예제 #9
0
파일: delete.c 프로젝트: nobled/gpgme
/* Delete KEY from the keyring.  If ALLOW_SECRET is non-zero, secret
   keys are also deleted.  */
gpgme_error_t
gpgme_op_delete (gpgme_ctx_t ctx, const gpgme_key_t key, int allow_secret)
{
  gpgme_error_t err;

  TRACE_BEG3 (DEBUG_CTX, "gpgme_op_delete", ctx,
	      "key=%p (%s), allow_secret=%i", key,
	      (key->subkeys && key->subkeys->fpr) ? 
	      key->subkeys->fpr : "invalid", allow_secret);
  err = delete_start (ctx, 1, key, allow_secret);
  if (!err)
    err = _gpgme_wait_one (ctx);
  return err;
}
예제 #10
0
파일: verify.c 프로젝트: nobled/gpgme
/* Decrypt ciphertext CIPHER and make a signature verification within
   CTX and store the resulting plaintext in PLAIN.  */
gpgme_error_t
gpgme_op_verify (gpgme_ctx_t ctx, gpgme_data_t sig, gpgme_data_t signed_text,
		 gpgme_data_t plaintext)
{
  gpgme_error_t err;

  TRACE_BEG3 (DEBUG_CTX, "gpgme_op_verify", ctx,
	      "sig=%p, signed_text=%p, plaintext=%p",
	      sig, signed_text, plaintext);

  err = verify_start (ctx, 1, sig, signed_text, plaintext);
  if (!err)
    err = _gpgme_wait_one (ctx);
  return TRACE_ERR (err);
}
예제 #11
0
파일: data-compat.c 프로젝트: nobled/gpgme
/* Create a new data buffer filled with the content of file FNAME.
   COPY must be non-zero (delayed reads are not supported yet).  */
gpgme_error_t
gpgme_data_new_from_file (gpgme_data_t *r_dh, const char *fname, int copy)
{
  gpgme_error_t err;
  struct stat statbuf;
  TRACE_BEG3 (DEBUG_DATA, "gpgme_data_new_from_filepart", r_dh,
	      "file_name=%s, copy=%i (%s)", fname, copy, copy ? "yes" : "no");

  if (!fname || !copy)
    return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));

  if (stat (fname, &statbuf) < 0)
    return TRACE_ERR (gpg_error_from_errno (errno));

  err = gpgme_data_new_from_filepart (r_dh, fname, NULL, 0, statbuf.st_size);
  return TRACE_ERR (err);
}
예제 #12
0
/* Create a new data buffer filled with the content of file FNAME.
   COPY must be non-zero (delayed reads are not supported yet).  */
gpgme_error_t
gpgme_data_new_from_file (gpgme_data_t *r_dh, const char *fname, int copy)
{
#if defined (HAVE_W32CE_SYSTEM) && defined (_MSC_VER)
  return gpgme_error (GPG_ERR_NOT_IMPLEMENTED);
#else
  gpgme_error_t err;
  struct stat statbuf;
  TRACE_BEG3 (DEBUG_DATA, "gpgme_data_new_from_filepart", r_dh,
	      "file_name=%s, copy=%i (%s)", fname, copy, copy ? "yes" : "no");

  if (!fname || !copy)
    return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));

  if (stat (fname, &statbuf) < 0)
    return TRACE_ERR (gpg_error_from_errno (errno));

  err = gpgme_data_new_from_filepart (r_dh, fname, NULL, 0, statbuf.st_size);
  return TRACE_ERR (err);
#endif
}
예제 #13
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;
}
예제 #14
0
static ssize_t
__assuan_read (assuan_context_t ctx, assuan_fd_t fd, void *buffer, size_t size)
{
  /* Due to the peculiarities of the W32 API we can't use read for a
     network socket and thus we try to use recv first and fallback to
     read if recv detects that it is not a network socket.  */
  int res;

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

#ifdef HAVE_W32CE_SYSTEM
  /* This is a bit of a hack to support stdin 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_STDIN)
    {
      int i = 0;
      int chr;
      while (i < size)
	{
	  chr = getchar();
	  if (chr == EOF)
	    break;
	  ((char*)buffer)[i++] = (char) chr;
	  if (chr == '\n')
	    break;
	}
      return TRACE_SYSRES (i);
    }
#endif

  res = recv (HANDLE2SOCKET (fd), buffer, size, 0);
  if (res == -1)
    {
      TRACE_LOG1 ("recv failed: rc=%d", (int)WSAGetLastError ());
      switch (WSAGetLastError ())
        {
        case WSAENOTSOCK:
          {
            DWORD nread = 0;
            
            res = ReadFile (fd, buffer, size, &nread, NULL);
            if (! res)
              {
                TRACE_LOG1 ("ReadFile failed: rc=%d", (int)GetLastError ());
                switch (GetLastError ())
                  {
                  case ERROR_BROKEN_PIPE:
		    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); 
                  }
                res = -1;
              }
            else
              res = (int) nread;
          }
          break;
          
        case WSAEWOULDBLOCK:
	  gpg_err_set_errno (EAGAIN);
	  break;

        case ERROR_BROKEN_PIPE:
	  gpg_err_set_errno (EPIPE);
	  break;

        default:
	  gpg_err_set_errno (EIO);
	  break;
        }
    }
  return TRACE_SYSRES (res);
}