Blame src/passphrase.c

Packit Service 672cf4
/* passphrase.c - Passphrase callback.
Packit Service 6c01f9
   Copyright (C) 2000 Werner Koch (dd9jn)
Packit Service 6c01f9
   Copyright (C) 2001, 2002, 2003, 2004, 2005 g10 Code GmbH
Packit Service 6c01f9
Packit Service 6c01f9
   This file is part of GPGME.
Packit Service 6c01f9
Packit Service 6c01f9
   GPGME is free software; you can redistribute it and/or modify it
Packit Service 6c01f9
   under the terms of the GNU Lesser General Public License as
Packit Service 6c01f9
   published by the Free Software Foundation; either version 2.1 of
Packit Service 6c01f9
   the License, or (at your option) any later version.
Packit Service 6c01f9
Packit Service 6c01f9
   GPGME is distributed in the hope that it will be useful, but
Packit Service 6c01f9
   WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 6c01f9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 6c01f9
   Lesser General Public License for more details.
Packit Service 6c01f9
Packit Service 6c01f9
   You should have received a copy of the GNU Lesser General Public
Packit Service 6c01f9
   License along with this program; if not, write to the Free Software
Packit Service 6c01f9
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
Packit Service 6c01f9
   02111-1307, USA.  */
Packit Service 672cf4
Packit Service 672cf4
#if HAVE_CONFIG_H
Packit Service 672cf4
#include <config.h>
Packit Service 672cf4
#endif
Packit Service 672cf4
#include <stdio.h>
Packit Service 672cf4
#include <stdlib.h>
Packit Service 672cf4
#include <string.h>
Packit Service 672cf4
#include <assert.h>
Packit Service 672cf4
#include <errno.h>
Packit Service 672cf4
Packit Service 672cf4
#include "gpgme.h"
Packit Service 672cf4
#include "context.h"
Packit Service 672cf4
#include "ops.h"
Packit Service 672cf4
#include "util.h"
Packit Service 672cf4
#include "debug.h"
Packit Service 672cf4
Packit Service 672cf4

Packit Service 672cf4
typedef struct
Packit Service 672cf4
{
Packit Service 672cf4
  int no_passphrase;
Packit Service 672cf4
  char *uid_hint;
Packit Service 672cf4
  char *passphrase_info;
Packit Service 672cf4
  int bad_passphrase;
Packit Service 672cf4
  char *maxlen;
Packit Service 672cf4
} *op_data_t;
Packit Service 672cf4
Packit Service 672cf4
Packit Service 672cf4
static void
Packit Service 672cf4
release_op_data (void *hook)
Packit Service 672cf4
{
Packit Service 672cf4
  op_data_t opd = (op_data_t) hook;
Packit Service 672cf4
Packit Service 672cf4
  if (opd->passphrase_info)
Packit Service 672cf4
    free (opd->passphrase_info);
Packit Service 672cf4
  if (opd->uid_hint)
Packit Service 672cf4
    free (opd->uid_hint);
Packit Service 672cf4
  free (opd->maxlen);
Packit Service 672cf4
}
Packit Service 672cf4
Packit Service 672cf4

Packit Service 672cf4
gpgme_error_t
Packit Service 672cf4
_gpgme_passphrase_status_handler (void *priv, gpgme_status_code_t code,
Packit Service 672cf4
				  char *args)
Packit Service 672cf4
{
Packit Service 672cf4
  gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
Packit Service 672cf4
  gpgme_error_t err;
Packit Service 672cf4
  void *hook;
Packit Service 672cf4
  op_data_t opd;
Packit Service 672cf4
Packit Service 672cf4
  err = _gpgme_op_data_lookup (ctx, OPDATA_PASSPHRASE, &hook,
Packit Service 672cf4
			       sizeof (*opd), release_op_data);
Packit Service 672cf4
  opd = hook;
Packit Service 672cf4
  if (err)
Packit Service 672cf4
    return err;
Packit Service 672cf4
Packit Service 672cf4
  switch (code)
Packit Service 672cf4
    {
Packit Service 672cf4
    case GPGME_STATUS_INQUIRE_MAXLEN:
Packit Service 672cf4
      free (opd->maxlen);
Packit Service 672cf4
      if (!(opd->maxlen = strdup (args)))
Packit Service 672cf4
        return gpg_error_from_syserror ();
Packit Service 672cf4
      break;
Packit Service 672cf4
    case GPGME_STATUS_USERID_HINT:
Packit Service 672cf4
      if (opd->uid_hint)
Packit Service 672cf4
	free (opd->uid_hint);
Packit Service 672cf4
      if (!(opd->uid_hint = strdup (args)))
Packit Service 672cf4
        return gpg_error_from_syserror ();
Packit Service 672cf4
      break;
Packit Service 672cf4
Packit Service 672cf4
    case GPGME_STATUS_BAD_PASSPHRASE:
Packit Service 672cf4
      opd->bad_passphrase++;
Packit Service 672cf4
      opd->no_passphrase = 0;
Packit Service 672cf4
      break;
Packit Service 672cf4
Packit Service 672cf4
    case GPGME_STATUS_GOOD_PASSPHRASE:
Packit Service 672cf4
      opd->bad_passphrase = 0;
Packit Service 672cf4
      opd->no_passphrase = 0;
Packit Service 672cf4
      break;
Packit Service 672cf4
Packit Service 672cf4
    case GPGME_STATUS_NEED_PASSPHRASE:
Packit Service 672cf4
    case GPGME_STATUS_NEED_PASSPHRASE_SYM:
Packit Service 672cf4
    case GPGME_STATUS_NEED_PASSPHRASE_PIN:
Packit Service 672cf4
      if (opd->passphrase_info)
Packit Service 672cf4
	free (opd->passphrase_info);
Packit Service 672cf4
      opd->passphrase_info = strdup (args);
Packit Service 672cf4
      if (!opd->passphrase_info)
Packit Service 672cf4
	return gpg_error_from_syserror ();
Packit Service 672cf4
      break;
Packit Service 672cf4
Packit Service 672cf4
    case GPGME_STATUS_MISSING_PASSPHRASE:
Packit Service 672cf4
      opd->no_passphrase = 1;
Packit Service 672cf4
      break;
Packit Service 672cf4
Packit Service 672cf4
    case GPGME_STATUS_EOF:
Packit Service 672cf4
      if (opd->no_passphrase || opd->bad_passphrase)
Packit Service 672cf4
	return gpg_error (GPG_ERR_BAD_PASSPHRASE);
Packit Service 672cf4
      break;
Packit Service 672cf4
Packit Service 672cf4
    case GPGME_STATUS_ERROR:
Packit Service 672cf4
      /* We abuse this status handler to forward ERROR status codes to
Packit Service 672cf4
         the caller.  */
Packit Service 672cf4
      if (ctx->status_cb && !ctx->full_status)
Packit Service 672cf4
        {
Packit Service 672cf4
          err = ctx->status_cb (ctx->status_cb_value, "ERROR", args);
Packit Service 672cf4
          if (err)
Packit Service 672cf4
            return err;
Packit Service 672cf4
        }
Packit Service 672cf4
      break;
Packit Service 672cf4
Packit Service 672cf4
    case GPGME_STATUS_FAILURE:
Packit Service 672cf4
      /* We abuse this status handler to forward FAILURE status codes
Packit Service 672cf4
         to the caller.  */
Packit Service 672cf4
      if (ctx->status_cb && !ctx->full_status)
Packit Service 672cf4
        {
Packit Service 672cf4
          err = ctx->status_cb (ctx->status_cb_value, "FAILURE", args);
Packit Service 672cf4
          if (err)
Packit Service 672cf4
            return err;
Packit Service 672cf4
        }
Packit Service 672cf4
      break;
Packit Service 672cf4
Packit Service 672cf4
Packit Service 672cf4
    default:
Packit Service 672cf4
      /* Ignore all other codes.  */
Packit Service 672cf4
      break;
Packit Service 672cf4
    }
Packit Service 672cf4
  return 0;
Packit Service 672cf4
}
Packit Service 672cf4
Packit Service 672cf4
Packit Service 672cf4
gpgme_error_t
Packit Service 672cf4
_gpgme_passphrase_command_handler (void *priv, gpgme_status_code_t code,
Packit Service 672cf4
				   const char *key, int fd, int *processed)
Packit Service 672cf4
{
Packit Service 672cf4
  gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
Packit Service 672cf4
  gpgme_error_t err;
Packit Service 672cf4
  void *hook;
Packit Service 672cf4
  op_data_t opd;
Packit Service 672cf4
Packit Service 672cf4
  assert (ctx->passphrase_cb);
Packit Service 672cf4
Packit Service 672cf4
  err = _gpgme_op_data_lookup (ctx, OPDATA_PASSPHRASE, &hook,
Packit Service 672cf4
			       sizeof (*opd), release_op_data);
Packit Service 672cf4
  opd = hook;
Packit Service 672cf4
  if (err)
Packit Service 672cf4
    return err;
Packit Service 672cf4
Packit Service 672cf4
  if (code == GPGME_STATUS_GET_HIDDEN
Packit Service 672cf4
      && (!strcmp (key, "passphrase.enter")
Packit Service 672cf4
          || !strcmp (key, "passphrase.pin.ask")))
Packit Service 672cf4
    {
Packit Service 672cf4
      if (processed)
Packit Service 672cf4
	*processed = 1;
Packit Service 672cf4
Packit Service 672cf4
      /* Fake a status line to to convey the MAXLEN info.  */
Packit Service 672cf4
      if (ctx->status_cb && opd->maxlen)
Packit Service 672cf4
        err = ctx->status_cb (ctx->status_cb_value, "INQUIRE_MAXLEN",
Packit Service 672cf4
                              opd->maxlen);
Packit Service 672cf4
Packit Service 672cf4
      if (!err)
Packit Service 672cf4
        err = ctx->passphrase_cb (ctx->passphrase_cb_value,
Packit Service 672cf4
                                  opd->uid_hint, opd->passphrase_info,
Packit Service 672cf4
                                  opd->bad_passphrase, fd);
Packit Service 672cf4
Packit Service 672cf4
      /* Reset bad passphrase flag, in case it is correct now.  */
Packit Service 672cf4
      opd->bad_passphrase = 0;
Packit Service 672cf4
Packit Service 672cf4
      return err;
Packit Service 672cf4
    }
Packit Service 672cf4
Packit Service 672cf4
  return 0;
Packit Service 672cf4
}