Blame src/passphrase.c

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