Exemple #1
0
/* Call the Entry and ask for the PIN.  We do check for a valid PIN
   number here and repeat it as long as we have invalid formed
   numbers. */
int
agent_askpin (ctrl_t ctrl,
              const char *desc_text, const char *prompt_text,
              const char *initial_errtext,
              struct pin_entry_info_s *pininfo)
{
  int rc;
  char line[ASSUAN_LINELENGTH];
  struct entry_parm_s parm;
  const char *errtext = NULL;
  int is_pin = 0;
  int saveflag;
  int close_button;

  if (opt.batch)
    return 0; /* fixme: we should return BAD PIN */

  if (ctrl->pinentry_mode != PINENTRY_MODE_ASK)
    {
      if (ctrl->pinentry_mode == PINENTRY_MODE_CANCEL)
        return gpg_error (GPG_ERR_CANCELED);
      if (ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK)
        {
	  unsigned char *passphrase;
	  size_t size;

	  *pininfo->pin = 0; /* Reset the PIN. */
	  rc = pinentry_loopback(ctrl, "PASSPHRASE", &passphrase, &size,
		  pininfo->max_length);
	  if (rc)
	    return rc;

	  memcpy(&pininfo->pin, passphrase, size);
	  xfree(passphrase);
	  pininfo->pin[size] = 0;
	  if (pininfo->check_cb)
	    {
	      /* More checks by utilizing the optional callback. */
	      pininfo->cb_errtext = NULL;
	      rc = pininfo->check_cb (pininfo);
	    }
	  return rc;
	}
      return gpg_error(GPG_ERR_NO_PIN_ENTRY);
    }

  if (!pininfo || pininfo->max_length < 1)
    return gpg_error (GPG_ERR_INV_VALUE);
  if (!desc_text && pininfo->min_digits)
    desc_text = _("Please enter your PIN, so that the secret key "
                  "can be unlocked for this session");
  else if (!desc_text)
    desc_text = _("Please enter your passphrase, so that the secret key "
                  "can be unlocked for this session");

  if (prompt_text)
    is_pin = !!strstr (prompt_text, "PIN");
  else
    is_pin = desc_text && strstr (desc_text, "PIN");

  rc = start_pinentry (ctrl);
  if (rc)
    return rc;

  snprintf (line, DIM(line)-1, "SETDESC %s", desc_text);
  line[DIM(line)-1] = 0;
  rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
  if (rc)
    return unlock_pinentry (rc);

  snprintf (line, DIM(line)-1, "SETPROMPT %s",
            prompt_text? prompt_text : is_pin? "PIN:" : "Passphrase:");
  line[DIM(line)-1] = 0;
  rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
  if (rc)
    return unlock_pinentry (rc);

  /* If a passphrase quality indicator has been requested and a
     minimum passphrase length has not been disabled, send the command
     to the pinentry.  */
  if (pininfo->with_qualitybar && opt.min_passphrase_len )
    {
      rc = setup_qualitybar ();
      if (rc)
        return unlock_pinentry (rc);
    }

  if (initial_errtext)
    {
      snprintf (line, DIM(line)-1, "SETERROR %s", initial_errtext);
      line[DIM(line)-1] = 0;
      rc = assuan_transact (entry_ctx, line,
                            NULL, NULL, NULL, NULL, NULL, NULL);
      if (rc)
        return unlock_pinentry (rc);
    }

  for (;pininfo->failed_tries < pininfo->max_tries; pininfo->failed_tries++)
    {
      memset (&parm, 0, sizeof parm);
      parm.size = pininfo->max_length;
      *pininfo->pin = 0; /* Reset the PIN. */
      parm.buffer = (unsigned char*)pininfo->pin;

      if (errtext)
        {
          /* TRANSLATORS: The string is appended to an error message in
             the pinentry.  The %s is the actual error message, the
             two %d give the current and maximum number of tries. */
          snprintf (line, DIM(line)-1, _("SETERROR %s (try %d of %d)"),
                    errtext, pininfo->failed_tries+1, pininfo->max_tries);
          line[DIM(line)-1] = 0;
          rc = assuan_transact (entry_ctx, line,
                                NULL, NULL, NULL, NULL, NULL, NULL);
          if (rc)
            return unlock_pinentry (rc);
          errtext = NULL;
        }

      saveflag = assuan_get_flag (entry_ctx, ASSUAN_CONFIDENTIAL);
      assuan_begin_confidential (entry_ctx);
      close_button = 0;
      rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm,
                            inq_quality, entry_ctx,
                            close_button_status_cb, &close_button);
      assuan_set_flag (entry_ctx, ASSUAN_CONFIDENTIAL, saveflag);
      /* Most pinentries out in the wild return the old Assuan error code
         for canceled which gets translated to an assuan Cancel error and
         not to the code for a user cancel.  Fix this here. */
      if (rc && gpg_err_source (rc)
          && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
        rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);

      /* Change error code in case the window close button was clicked
         to cancel the operation.  */
      if (close_button && gpg_err_code (rc) == GPG_ERR_CANCELED)
        rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_FULLY_CANCELED);

      if (gpg_err_code (rc) == GPG_ERR_ASS_TOO_MUCH_DATA)
        errtext = is_pin? _("PIN too long")
                        : _("Passphrase too long");
      else if (rc)
        return unlock_pinentry (rc);

      if (!errtext && pininfo->min_digits)
        {
          /* do some basic checks on the entered PIN. */
          if (!all_digitsp (pininfo->pin))
            errtext = _("Invalid characters in PIN");
          else if (pininfo->max_digits
                   && strlen (pininfo->pin) > pininfo->max_digits)
            errtext = _("PIN too long");
          else if (strlen (pininfo->pin) < pininfo->min_digits)
            errtext = _("PIN too short");
        }

      if (!errtext && pininfo->check_cb)
        {
          /* More checks by utilizing the optional callback. */
          pininfo->cb_errtext = NULL;
          rc = pininfo->check_cb (pininfo);
          if (rc == -1 && pininfo->cb_errtext)
            errtext = pininfo->cb_errtext;
          else if (gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE
                   || gpg_err_code (rc) == GPG_ERR_BAD_PIN)
            errtext = (is_pin? _("Bad PIN")
                       : _("Bad Passphrase"));
          else if (rc)
            return unlock_pinentry (rc);
        }

      if (!errtext)
        return unlock_pinentry (0); /* okay, got a PIN or passphrase */
    }

  return unlock_pinentry (gpg_error (pininfo->min_digits? GPG_ERR_BAD_PIN
                          : GPG_ERR_BAD_PASSPHRASE));
}
Exemple #2
0
/* Ask for the passphrase using the supplied arguments.  The returned
   passphrase needs to be freed by the caller. */
int
agent_get_passphrase (ctrl_t ctrl,
                      char **retpass, const char *desc, const char *prompt,
                      const char *errtext, int with_qualitybar)
{

  int rc;
  char line[ASSUAN_LINELENGTH];
  struct entry_parm_s parm;
  int saveflag;
  int close_button;

  *retpass = NULL;
  if (opt.batch)
    return gpg_error (GPG_ERR_BAD_PASSPHRASE);

  if (ctrl->pinentry_mode != PINENTRY_MODE_ASK)
    {
      if (ctrl->pinentry_mode == PINENTRY_MODE_CANCEL)
        return gpg_error (GPG_ERR_CANCELED);

      if (ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK)
        {
	  size_t size;
	  size_t len = ASSUAN_LINELENGTH/2;
	  unsigned char *buffer = gcry_malloc_secure (len);

	  rc = pinentry_loopback(ctrl, "PASSPHRASE", &buffer, &size, len);
	  if (rc)
	    xfree(buffer);
	  else
	    {
	      buffer[size] = 0;
	      *retpass = buffer;
	    }
	  return rc;
        }
      return gpg_error (GPG_ERR_NO_PIN_ENTRY);
    }

  rc = start_pinentry (ctrl);
  if (rc)
    return rc;

  if (!prompt)
    prompt = desc && strstr (desc, "PIN")? "PIN": _("Passphrase");


  if (desc)
    snprintf (line, DIM(line)-1, "SETDESC %s", desc);
  else
    snprintf (line, DIM(line)-1, "RESET");
  line[DIM(line)-1] = 0;
  rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
  if (rc)
    return unlock_pinentry (rc);

  snprintf (line, DIM(line)-1, "SETPROMPT %s", prompt);
  line[DIM(line)-1] = 0;
  rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
  if (rc)
    return unlock_pinentry (rc);

  if (with_qualitybar && opt.min_passphrase_len)
    {
      rc = setup_qualitybar ();
      if (rc)
        return unlock_pinentry (rc);
    }

  if (errtext)
    {
      snprintf (line, DIM(line)-1, "SETERROR %s", errtext);
      line[DIM(line)-1] = 0;
      rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
      if (rc)
        return unlock_pinentry (rc);
    }

  memset (&parm, 0, sizeof parm);
  parm.size = ASSUAN_LINELENGTH/2 - 5;
  parm.buffer = gcry_malloc_secure (parm.size+10);
  if (!parm.buffer)
    return unlock_pinentry (out_of_core ());

  saveflag = assuan_get_flag (entry_ctx, ASSUAN_CONFIDENTIAL);
  assuan_begin_confidential (entry_ctx);
  close_button = 0;
  rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm,
                        inq_quality, entry_ctx,
                        close_button_status_cb, &close_button);
  assuan_set_flag (entry_ctx, ASSUAN_CONFIDENTIAL, saveflag);
  /* Most pinentries out in the wild return the old Assuan error code
     for canceled which gets translated to an assuan Cancel error and
     not to the code for a user cancel.  Fix this here. */
  if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
    rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
  /* Change error code in case the window close button was clicked
     to cancel the operation.  */
  if (close_button && gpg_err_code (rc) == GPG_ERR_CANCELED)
    rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_FULLY_CANCELED);

  if (rc)
    xfree (parm.buffer);
  else
    *retpass = parm.buffer;
  return unlock_pinentry (rc);
}
Exemple #3
0
/* Ask for the passphrase using the supplied arguments.  The returned
   passphrase needs to be freed by the caller. */
int 
agent_get_passphrase (ctrl_t ctrl,
                      char **retpass, const char *desc, const char *prompt,
                      const char *errtext, int with_qualitybar)
{

  int rc;
  char line[ASSUAN_LINELENGTH];
  struct entry_parm_s parm;
  int saveflag;

  *retpass = NULL;
  if (opt.batch)
    return gpg_error (GPG_ERR_BAD_PASSPHRASE); 

  rc = start_pinentry (ctrl);
  if (rc)
    return rc;

  if (!prompt)
    prompt = desc && strstr (desc, "PIN")? "PIN": _("Passphrase");


  if (desc)
    snprintf (line, DIM(line)-1, "SETDESC %s", desc);
  else
    snprintf (line, DIM(line)-1, "RESET");
  line[DIM(line)-1] = 0;
  rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
  if (rc)
    return unlock_pinentry (rc);

  snprintf (line, DIM(line)-1, "SETPROMPT %s", prompt);
  line[DIM(line)-1] = 0;
  rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
  if (rc)
    return unlock_pinentry (rc);

  if (with_qualitybar && opt.min_passphrase_len)
    {
      rc = setup_qualitybar ();
      if (rc)
        return unlock_pinentry (rc);
    }

  if (errtext)
    {
      snprintf (line, DIM(line)-1, "SETERROR %s", errtext);
      line[DIM(line)-1] = 0;
      rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
      if (rc)
        return unlock_pinentry (rc);
    }

  memset (&parm, 0, sizeof parm);
  parm.size = ASSUAN_LINELENGTH/2 - 5;
  parm.buffer = gcry_malloc_secure (parm.size+10);
  if (!parm.buffer)
    return unlock_pinentry (out_of_core ());

  saveflag = assuan_get_flag (entry_ctx, ASSUAN_CONFIDENTIAL);
  assuan_begin_confidential (entry_ctx);
  rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm,
                        inq_quality, entry_ctx, NULL, NULL);
  assuan_set_flag (entry_ctx, ASSUAN_CONFIDENTIAL, saveflag);
  /* Most pinentries out in the wild return the old Assuan error code
     for canceled which gets translated to an assuan Cancel error and
     not to the code for a user cancel.  Fix this here. */
  if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
    rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
  if (rc)
    xfree (parm.buffer);
  else
    *retpass = parm.buffer;
  return unlock_pinentry (rc);
}