Beispiel #1
0
/**
 * crypt_invoke_message - Display an informative message
 * @param type Crypto type, see #SecurityFlags
 *
 * Show a message that a backend will be invoked.
 */
void crypt_invoke_message(SecurityFlags type)
{
  if (((WithCrypto & APPLICATION_PGP) != 0) && (type & APPLICATION_PGP))
    mutt_message(_("Invoking PGP..."));
  else if (((WithCrypto & APPLICATION_SMIME) != 0) && (type & APPLICATION_SMIME))
    mutt_message(_("Invoking S/MIME..."));
}
Beispiel #2
0
/* Show a message that a backend will be invoked. */
void crypt_invoke_message(int type)
{
	if ((WithCrypto & APPLICATION_PGP) && (type & APPLICATION_PGP))
		mutt_message("Invoking PGP...");
	else if ((WithCrypto & APPLICATION_SMIME) && (type & APPLICATION_SMIME))
		mutt_message("Invoking S/MIME...");
}
Beispiel #3
0
/* imap_auth_login: Plain LOGIN support */
imap_auth_res_t imap_auth_login (IMAP_DATA* idata, const char* method)
{
	char q_user[SHORT_STRING], q_pass[SHORT_STRING];
	char buf[STRING];
	int rc;

	if (bit_val(idata->capabilities, LOGINDISABLED))
	{
		mutt_message("LOGIN disabled on this server.");
		return IMAP_AUTH_UNAVAIL;
	}

	if (mutt_account_getuser (&idata->conn->account))
		return IMAP_AUTH_FAILURE;
	if (mutt_account_getpass (&idata->conn->account))
		return IMAP_AUTH_FAILURE;

	mutt_message("Logging in...");

	imap_quote_string (q_user, sizeof (q_user), idata->conn->account.user);
	imap_quote_string (q_pass, sizeof (q_pass), idata->conn->account.pass);

	snprintf (buf, sizeof (buf), "LOGIN %s %s", q_user, q_pass);
	rc = imap_exec (idata, buf, IMAP_CMD_FAIL_OK | IMAP_CMD_PASS);

	if (!rc)
	{
		mutt_clear_error(); /* clear "Logging in...".  fixes #3524 */
		return IMAP_AUTH_SUCCESS;
	}

	mutt_error("Login failed.");
	mutt_sleep (2);
	return IMAP_AUTH_FAILURE;
}
Beispiel #4
0
/**
 * execute_command - Run a system command
 * @param m        Mailbox to work with
 * @param command  Command string to execute
 * @param progress Message to show the user
 * @retval 1 Success
 * @retval 0 Failure
 *
 * Run the supplied command, taking care of all the NeoMutt requirements,
 * such as locking files and blocking signals.
 */
static int execute_command(struct Mailbox *m, const char *command, const char *progress)
{
  int rc = 1;
  char sys_cmd[STR_COMMAND];

  if (!m || !command || !progress)
    return 0;

  if (!m->quiet)
  {
    mutt_message(progress, m->realpath);
  }

  mutt_sig_block();
  endwin();
  fflush(stdout);

  expand_command_str(m, command, sys_cmd, sizeof(sys_cmd));

  if (mutt_system(sys_cmd) != 0)
  {
    rc = 0;
    mutt_any_key_to_continue(NULL);
    mutt_error(_("Error running \"%s\""), sys_cmd);
  }

  mutt_sig_unblock();

  return rc;
}
Beispiel #5
0
static int add_entropy (const char *file)
{
        struct stat st;
        int n = -1;

        if (!file) return 0;

        if (stat (file, &st) == -1)
                return errno == ENOENT ? 0 : -1;

        mutt_message (_("Filling entropy pool: %s...\n"),
                file);

/* check that the file permissions are secure */
        if (st.st_uid != getuid () ||
                ((st.st_mode & (S_IWGRP | S_IRGRP)) != 0) ||
        ((st.st_mode & (S_IWOTH | S_IROTH)) != 0)) {
                mutt_error (_("%s has insecure permissions!"), file);
                mutt_sleep (2);
                return -1;
        }

#ifdef HAVE_RAND_EGD
        n = RAND_egd (file);
#endif
        if (n <= 0)
                n = RAND_load_file (file, -1);

#ifndef HAVE_RAND_STATUS
        if (n > 0) entropy_byte_count += n;
#endif
        return n;
}
Beispiel #6
0
/* enter a mutt command */
void mutt_enter_command (void)
{
  BUFFER err, token;
  char buffer[LONG_STRING];
  int r;

  buffer[0] = 0;
  if (mutt_get_field (":", buffer, sizeof (buffer), M_COMMAND) != 0 || !buffer[0])
    return;
  mutt_buffer_init (&err);
  err.dsize = STRING;
  err.data = safe_malloc(err.dsize);
  mutt_buffer_init (&token);
  r = mutt_parse_rc_line (buffer, &token, &err);
  FREE (&token.data);
  if (err.data[0])
  {
    /* since errbuf could potentially contain printf() sequences in it,
       we must call mutt_error() in this fashion so that vsprintf()
       doesn't expect more arguments that we passed */
    if (r == 0)
      mutt_message ("%s", err.data);
    else
      mutt_error ("%s", err.data);
  }

  FREE (&err.data);
}
Beispiel #7
0
static QUERY *run_query (char *s, int quiet)
{
        FILE *fp;
        QUERY *first = NULL;
        QUERY *cur = NULL;
        char cmd[_POSIX_PATH_MAX];
        char *buf = NULL;
        size_t buflen;
        int dummy = 0;
        char msg[STRING];
        char *p;
        pid_t thepid;

        mutt_expand_file_fmt (cmd, sizeof(cmd), QueryCmd, s);

        if ((thepid = mutt_create_filter (cmd, NULL, &fp, NULL)) < 0) {
                dprint (1, (debugfile, "unable to fork command: %s", cmd));
                return 0;
        }
        if (!quiet)
                mutt_message _("Waiting for response...");
        fgets (msg, sizeof (msg), fp);
        if ((p = strrchr (msg, '\n')))
                *p = '\0';
        while ((buf = mutt_read_line (buf, &buflen, fp, &dummy, 0)) != NULL) {
                if ((p = strtok(buf, "\t\n"))) {
                        if (first == NULL) {
                                first = (QUERY *) safe_calloc (1, sizeof (QUERY));
                                cur = first;
                        }
                        else {
                                cur->next = (QUERY *) safe_calloc (1, sizeof (QUERY));
                                cur = cur->next;
                        }

                        cur->addr = rfc822_parse_adrlist (cur->addr, p);
                        p = strtok(NULL, "\t\n");
                        if (p) {
                                cur->name = safe_strdup (p);
                                p = strtok(NULL, "\t\n");
                                if (p)
                                        cur->other = safe_strdup (p);
                        }
                }
        }
        FREE (&buf);
        safe_fclose (&fp);
        if (mutt_wait_filter (thepid)) {
                dprint (1, (debugfile, "Error: %s\n", msg));
                if (!quiet)  mutt_error ("%s", msg);
        }
        else {
                if (!quiet)
                        mutt_message ("%s", msg);
        }

        return first;
}
Beispiel #8
0
/**
 * mutt_progress_init - Set up a progress bar
 * @param progress Progress bar
 * @param msg      Message to display
 * @param flags    Flags, e.g. #MUTT_PROGRESS_SIZE
 * @param inc      Increments to display (0 disables updates)
 * @param size     Total size of expected file / traffic
 */
void mutt_progress_init(struct Progress *progress, const char *msg,
                        unsigned short flags, unsigned short inc, size_t size)
{
  struct timeval tv = { 0, 0 };

  if (!progress)
    return;
  if (OptNoCurses)
    return;

  memset(progress, 0, sizeof(struct Progress));
  progress->inc = inc;
  progress->flags = flags;
  progress->msg = msg;
  progress->size = size;
  if (progress->size != 0)
  {
    if (progress->flags & MUTT_PROGRESS_SIZE)
    {
      mutt_str_pretty_size(progress->sizestr, sizeof(progress->sizestr),
                           progress->size);
    }
    else
      snprintf(progress->sizestr, sizeof(progress->sizestr), "%zu", progress->size);
  }
  if (inc == 0)
  {
    if (size != 0)
      mutt_message("%s (%s)", msg, progress->sizestr);
    else
      mutt_message(msg);
    return;
  }
  if (gettimeofday(&tv, NULL) < 0)
    mutt_debug(LL_DEBUG1, "gettimeofday failed: %d\n", errno);
  /* if timestamp is 0 no time-based suppression is done */
  if (C_TimeInc != 0)
  {
    progress->timestamp =
        ((unsigned int) tv.tv_sec * 1000) + (unsigned int) (tv.tv_usec / 1000);
  }
  mutt_progress_update(progress, 0, 0);
}
/* return 0 on success, -1 on failure */
int mutt_sync_compressed (CONTEXT * ctx)
{
    char *cmd;
    int rc = 0;
    FILE *fp;
    COMPRESS_INFO *ci = (COMPRESS_INFO *) ctx->compressinfo;

    if (!ctx->quiet)
        mutt_message (_("Compressing %s..."), ctx->realpath);

    cmd = get_compression_cmd (ci->close, ctx);
    if (cmd == NULL)
        return (-1);

    if ((fp = fopen (ctx->realpath, "a")) == NULL) {
        mutt_perror (ctx->realpath);
        mem_free (&cmd);
        return (-1);
    }
    mutt_block_signals ();
    if (mbox_lock_compressed (ctx, fp, 1, 1) == -1) {
        fclose (fp);
        mutt_unblock_signals ();
        mutt_error _("Unable to lock mailbox!");

        store_size (ctx);

        mem_free (&cmd);
        return (-1);
    }

    debug_print (2, ("CompressCommand: '%s'\n", cmd));

    endwin ();
    fflush (stdout);
    sprintf (echo_cmd, _("echo Compressing %s..."), ctx->realpath);
    mutt_system (echo_cmd);
    if (mutt_system (cmd)) {
        mutt_any_key_to_continue (NULL);
        mutt_error (_
                    ("%s: Error compressing mailbox! Original mailbox deleted, uncompressed one kept!\n"),
                    ctx->path);
        rc = -1;
    }

    mbox_unlock_compressed (ctx, fp);
    mutt_unblock_signals ();
    fclose (fp);

    mem_free (&cmd);

    store_size (ctx);

    return (rc);
}
Beispiel #10
0
/**
 * imap_auth_oauth - Authenticate an IMAP connection using OAUTHBEARER
 * @param adata Imap Account data
 * @param method Name of this authentication method (UNUSED)
 * @retval num Result, e.g. #IMAP_AUTH_SUCCESS
 */
enum ImapAuthRes imap_auth_oauth(struct ImapAccountData *adata, const char *method)
{
  char *ibuf = NULL;
  char *oauthbearer = NULL;
  int ilen;
  int rc;

  /* For now, we only support SASL_IR also and over TLS */
  if (!(adata->capabilities & IMAP_CAP_AUTH_OAUTHBEARER) ||
      !(adata->capabilities & IMAP_CAP_SASL_IR) || !adata->conn->ssf)
  {
    return IMAP_AUTH_UNAVAIL;
  }

  /* If they did not explicitly request or configure oauth then fail quietly */
  if (!(method || (C_ImapOauthRefreshCommand && *C_ImapOauthRefreshCommand)))
    return IMAP_AUTH_UNAVAIL;

  mutt_message(_("Authenticating (OAUTHBEARER)..."));

  /* We get the access token from the imap_oauth_refresh_command */
  oauthbearer = mutt_account_getoauthbearer(&adata->conn->account);
  if (!oauthbearer)
    return IMAP_AUTH_FAILURE;

  ilen = mutt_str_strlen(oauthbearer) + 30;
  ibuf = mutt_mem_malloc(ilen);
  snprintf(ibuf, ilen, "AUTHENTICATE OAUTHBEARER %s", oauthbearer);

  /* This doesn't really contain a password, but the token is good for
   * an hour, so suppress it anyways.  */
  rc = imap_exec(adata, ibuf, IMAP_CMD_PASS);

  FREE(&oauthbearer);
  FREE(&ibuf);

  if (rc != IMAP_EXEC_SUCCESS)
  {
    /* The error response was in SASL continuation, so continue the SASL
     * to cause a failure and exit SASL input.  See RFC 7628 3.2.3 */
    mutt_socket_send(adata->conn, "\001");
    rc = imap_exec(adata, ibuf, IMAP_CMD_NO_FLAGS);
  }

  if (rc == IMAP_EXEC_SUCCESS)
  {
    mutt_clear_error();
    return IMAP_AUTH_SUCCESS;
  }

  mutt_error(_("OAUTHBEARER authentication failed."));
  return IMAP_AUTH_FAILURE;
}
Beispiel #11
0
void mutt_print_message (HEADER *h)
{

        if (quadoption (OPT_PRINT) && (!PrintCmd || !*PrintCmd)) {
                mutt_message (_("No printing command has been defined."));
                return;
        }

        if (query_quadoption (OPT_PRINT,
                h ? _("Print message?") : _("Print tagged messages?"))
                != M_YES)
                return;

        if (_mutt_pipe_message (h, PrintCmd,
                option (OPTPRINTDECODE),
                1,
                option (OPTPRINTSPLIT),
                "\f") == 0)
                mutt_message (h ? _("Message printed") : _("Messages printed"));
        else
                mutt_message (h ? _("Message could not be printed") :
                _("Messages could not be printed"));
}
Beispiel #12
0
static int register_gpgme()
{
	if (!bit_val(options, OPTCRYPTUSEGPGME))
	{
		mutt_message(("\"crypt_use_gpgme\" set"
			      " but not built with GPGME support."));
		return 0;
	}
	else
	{
		crypto_module_register(&crypt_mod_pgp_gpgme);
		crypto_module_register(&crypt_mod_smime_gpgme);
		return 1;
	}
}
Beispiel #13
0
/* ssl_negotiate: After SSL state has been initialized, attempt to negotiate
 *   SSL over the wire, including certificate checks. */
static int ssl_negotiate (CONNECTION *conn, sslsockdata* ssldata)
{
  int err;
  const char* errmsg;

  SSL_set_mode (ssldata->ssl, SSL_MODE_AUTO_RETRY);

  if ((err = SSL_connect (ssldata->ssl)) != 1)
  {
    switch (SSL_get_error (ssldata->ssl, err))
    {
    case SSL_ERROR_SYSCALL:
      errmsg = _("I/O error");
      break;
    case SSL_ERROR_SSL:
      errmsg = ERR_error_string (ERR_get_error (), NULL);
      break;
    default:
      errmsg = _("unknown error");
    }

    mutt_error (_("SSL failed: %s"), errmsg);
    mutt_sleep (1);

    return -1;
  }

  ssldata->cert = SSL_get_peer_certificate (ssldata->ssl);
  if (!ssldata->cert)
  {
    mutt_error (_("Unable to get certificate from peer"));
    mutt_sleep (1);
    return -1;
  }

  if (!ssl_check_certificate (conn, ssldata))
    return -1;

  /* L10N:
     %1$s is version (e.g. "TLSv1.2")
     %2$s is cipher_version (e.g. "TLSv1/SSLv3")
     %3$s is cipher_name (e.g. "ECDHE-RSA-AES128-GCM-SHA256") */
  mutt_message (_("%s connection using %s (%s)"),
    SSL_get_version(ssldata->ssl), SSL_get_cipher_version (ssldata->ssl), SSL_get_cipher_name (ssldata->ssl));
  mutt_sleep (0);

  return 0;
}
Beispiel #14
0
/* ssl_negotiate: After SSL state has been initialised, attempt to negotiate
 *   SSL over the wire, including certificate checks. */
static int ssl_negotiate (CONNECTION *conn, sslsockdata* ssldata)
{
  int err;
  const char* errmsg;

#if OPENSSL_VERSION_NUMBER >= 0x00906000L
  /* This only exists in 0.9.6 and above. Without it we may get interrupted
   *   reads or writes. Bummer. */
  SSL_set_mode (ssldata->ssl, SSL_MODE_AUTO_RETRY);
#endif

  if ((err = SSL_connect (ssldata->ssl)) != 1)
  {
    switch (SSL_get_error (ssldata->ssl, err))
    {
    case SSL_ERROR_SYSCALL:
      errmsg = _("I/O error");
      break;
    case SSL_ERROR_SSL:
      errmsg = ERR_error_string (ERR_get_error (), NULL);
      break;
    default:
      errmsg = _("unknown error");
    }

    mutt_error (_("SSL failed: %s"), errmsg);
    mutt_sleep (1);

    return -1;
  }

  ssldata->cert = SSL_get_peer_certificate (ssldata->ssl);
  if (!ssldata->cert)
  {
    mutt_error (_("Unable to get certificate from peer"));
    mutt_sleep (1);
    return -1;
  }

  if (!ssl_check_certificate (conn, ssldata))
    return -1;

  mutt_message (_("%s connection using %s (%s)"),
    SSL_get_version(ssldata->ssl), SSL_get_cipher_version (ssldata->ssl), SSL_get_cipher_name (ssldata->ssl));
  mutt_sleep (0);

  return 0;
}
Beispiel #15
0
/**
 * crypt_forget_passphrase - Forget a passphrase and display a message
 */
void crypt_forget_passphrase(void)
{
  if (WithCrypto & APPLICATION_PGP)
    crypt_pgp_void_passphrase();

  if (WithCrypto & APPLICATION_SMIME)
    crypt_smime_void_passphrase();

  if (WithCrypto)
  {
    /* L10N: Due to the implementation details (e.g. some passwords are managed
       by gpg-agent) we cannot know whether we forgot zero, 1, 12, ...
       passwords. So in English we use "Passphrases". Your language might
       have other means to express this. */
    mutt_message(_("Passphrases forgotten"));
  }
}
Beispiel #16
0
/**
 * crypt_init - Initialise the crypto backends
 *
 * This calls CryptModuleSpecs::init()
 */
void crypt_init(void)
{
#ifdef CRYPT_BACKEND_CLASSIC_PGP
  if (
#ifdef CRYPT_BACKEND_GPGME
      (!C_CryptUseGpgme)
#else
      1
#endif
  )
    crypto_module_register(&CryptModPgpClassic);
#endif

#ifdef CRYPT_BACKEND_CLASSIC_SMIME
  if (
#ifdef CRYPT_BACKEND_GPGME
      (!C_CryptUseGpgme)
#else
      1
#endif
  )
    crypto_module_register(&CryptModSmimeClassic);
#endif

  if (C_CryptUseGpgme)
  {
#ifdef CRYPT_BACKEND_GPGME
    crypto_module_register(&CryptModPgpGpgme);
    crypto_module_register(&CryptModSmimeGpgme);
#else
    mutt_message(_("\"crypt_use_gpgme\" set"
                   " but not built with GPGME support"));
    if (mutt_any_key_to_continue(NULL) == -1)
      mutt_exit(1);
#endif
  }

#if defined(CRYPT_BACKEND_CLASSIC_PGP) ||                                      \
    defined(CRYPT_BACKEND_CLASSIC_SMIME) || defined(CRYPT_BACKEND_GPGME)
  if (CRYPT_MOD_CALL_CHECK(PGP, init))
    CRYPT_MOD_CALL(PGP, init)();

  if (CRYPT_MOD_CALL_CHECK(SMIME, init))
    CRYPT_MOD_CALL(SMIME, init)();
#endif
}
Beispiel #17
0
void crypt_init (void)
{
#ifdef CRYPT_BACKEND_CLASSIC_PGP
  if (
#ifdef CRYPT_BACKEND_GPGME
      (! option (OPTCRYPTUSEGPGME))
#else
       1
#endif
      )
    crypto_module_register (&crypt_mod_pgp_classic);
#endif

#ifdef CRYPT_BACKEND_CLASSIC_SMIME
  if (
#ifdef CRYPT_BACKEND_GPGME
      (! option (OPTCRYPTUSEGPGME))
#else
       1
#endif
      )
    crypto_module_register (&crypt_mod_smime_classic);
#endif

  if (option (OPTCRYPTUSEGPGME))
    {
#ifdef CRYPT_BACKEND_GPGME
      crypto_module_register (&crypt_mod_pgp_gpgme);
      crypto_module_register (&crypt_mod_smime_gpgme);
#else
      mutt_message (_("\"crypt_use_gpgme\" set"
                      " but not built with GPGME support."));
      if (mutt_any_key_to_continue (NULL) == -1)
	mutt_exit(1);
#endif
    }

#if defined CRYPT_BACKEND_CLASSIC_PGP || defined CRYPT_BACKEND_CLASSIC_SMIME || defined CRYPT_BACKEND_GPGME
  if (CRYPT_MOD_CALL_CHECK (PGP, init))
    (CRYPT_MOD_CALL (PGP, init)) ();

  if (CRYPT_MOD_CALL_CHECK (SMIME, init))
    (CRYPT_MOD_CALL (SMIME, init)) ();
#endif
}
Beispiel #18
0
void mutt_display_address (ENVELOPE *env)
{
  char *pfx = NULL;
  char buf[SHORT_STRING];
  ADDRESS *adr = NULL;

  adr = mutt_get_address (env, &pfx);

  if (!adr) return;
  
  /* 
   * Note: We don't convert IDNA to local representation this time.
   * That is intentional, so the user has an opportunity to copy &
   * paste the on-the-wire form of the address to other, IDN-unable
   * software. 
   */
  
  buf[0] = 0;
  rfc822_write_address (buf, sizeof (buf), adr, 0);
  mutt_message ("%s: %s", pfx, buf);
}
Beispiel #19
0
Datei: mh.c Projekt: hww3/pexts
static int maildir_parse_entry(CONTEXT *ctx, struct maildir ***last,
				const char *subdir, const char *fname,
				int *count, int is_old)
{
  struct maildir *entry;
  HEADER *h;
  char buf[_POSIX_PATH_MAX];

  if(subdir)
    snprintf(buf, sizeof(buf), "%s/%s/%s", ctx->path, subdir, fname);
  else
    snprintf(buf, sizeof(buf), "%s/%s", ctx->path, fname);
  
  if((h = maildir_parse_message(ctx->magic, buf, is_old)) != NULL)
  {
    if(count)
    {
      (*count)++;  
      if (!ctx->quiet && ReadInc && ((*count % ReadInc) == 0 || *count == 1))
	mutt_message (_("Reading %s... %d"), ctx->path, *count);
    }

    if (subdir)
    {
      snprintf (buf, sizeof (buf), "%s/%s", subdir, fname);
      h->path = safe_strdup (buf);
    }
    else
      h->path = safe_strdup (fname);
    
    entry = safe_calloc(sizeof(struct maildir), 1);
    entry->h = h;
    **last = entry;
    *last = &entry->next;
    
    return 0;
  }
  
  return -1;
}
Beispiel #20
0
/* imap_auth_sasl: Default authenticator if available. */
imap_auth_res_t imap_auth_sasl (IMAP_DATA* idata, const char* method)
{
  sasl_conn_t* saslconn;
  sasl_interact_t* interaction = NULL;
  int rc, irc;
  char buf[HUGE_STRING];
  const char* mech;
  const char *pc = NULL;
  unsigned int len, olen;
  unsigned char client_start;

  if (mutt_sasl_client_new (idata->conn, &saslconn) < 0)
  {
    dprint (1, (debugfile,
      "imap_auth_sasl: Error allocating SASL connection.\n"));
    return IMAP_AUTH_FAILURE;
  }

  rc = SASL_FAIL;

  /* If the user hasn't specified a method, use any available */
  if (!method)
  {
    method = idata->capstr;

    /* hack for SASL ANONYMOUS support:
     * 1. Fetch username. If it's "" or "anonymous" then
     * 2. attempt sasl_client_start with only "AUTH=ANONYMOUS" capability
     * 3. if sasl_client_start fails, fall through... */

    if (mutt_account_getuser (&idata->conn->account))
      return IMAP_AUTH_FAILURE;

    if (mutt_bit_isset (idata->capabilities, AUTH_ANON) &&
	(!idata->conn->account.user[0] ||
	 !ascii_strncmp (idata->conn->account.user, "anonymous", 9)))
      rc = sasl_client_start (saslconn, "AUTH=ANONYMOUS", NULL, &pc, &olen, 
                              &mech);
  } else if (!ascii_strcasecmp ("login", method) &&
	!strstr (NONULL (idata->capstr), "AUTH=LOGIN"))
    /* do not use SASL login for regular IMAP login (#3556) */
    return IMAP_AUTH_UNAVAIL;
  
  if (rc != SASL_OK && rc != SASL_CONTINUE)
    do
    {
      rc = sasl_client_start (saslconn, method, &interaction,
        &pc, &olen, &mech);
      if (rc == SASL_INTERACT)
	mutt_sasl_interact (interaction);
    }
    while (rc == SASL_INTERACT);

  client_start = (olen > 0);

  if (rc != SASL_OK && rc != SASL_CONTINUE)
  {
    if (method)
      dprint (2, (debugfile, "imap_auth_sasl: %s unavailable\n", method));
    else
      dprint (1, (debugfile, "imap_auth_sasl: Failure starting authentication exchange. No shared mechanisms?\n"));
    /* SASL doesn't support LOGIN, so fall back */

    return IMAP_AUTH_UNAVAIL;
  }

  mutt_message (_("Authenticating (%s)..."), mech);

  snprintf (buf, sizeof (buf), "AUTHENTICATE %s", mech);
  if (mutt_bit_isset (idata->capabilities, SASL_IR) && client_start)
  {
    len = mutt_strlen (buf);
    buf[len++] = ' ';
    if (sasl_encode64 (pc, olen, buf + len, sizeof (buf) - len, &olen) != SASL_OK)
    {
      dprint (1, (debugfile, "imap_auth_sasl: error base64-encoding client response.\n"));
      goto bail;
    }
    client_start = olen = 0;
  }
  imap_cmd_start (idata, buf);
  irc = IMAP_CMD_CONTINUE;

  /* looping protocol */
  while (rc == SASL_CONTINUE || olen > 0)
  {
    do
      irc = imap_cmd_step (idata);
    while (irc == IMAP_CMD_CONTINUE);

    if (irc == IMAP_CMD_BAD || irc == IMAP_CMD_NO)
      goto bail;

    if (irc == IMAP_CMD_RESPOND)
    {
      /* Exchange incorrectly returns +\r\n instead of + \r\n */
      if (idata->buf[1] == '\0')
      {
	buf[0] = '\0';
	len = 0;
      }
      else if (sasl_decode64 (idata->buf+2, strlen (idata->buf+2), buf,
			      LONG_STRING-1, &len) != SASL_OK)
      {
	dprint (1, (debugfile, "imap_auth_sasl: error base64-decoding server response.\n"));
	goto bail;
      }
    }

    /* client-start is only available with the SASL-IR extension, but
     * SASL 2.1 seems to want to use it regardless, at least for DIGEST
     * fast reauth. Override if the server sent an initial continuation */
    if (!client_start || buf[0])
    {
      do
      {
	rc = sasl_client_step (saslconn, buf, len, &interaction, &pc, &olen);
	if (rc == SASL_INTERACT)
	  mutt_sasl_interact (interaction);
      }
      while (rc == SASL_INTERACT);
    }
    else
      client_start = 0;

    /* send out response, or line break if none needed */
    if (olen)
    {
      if (sasl_encode64 (pc, olen, buf, sizeof (buf), &olen) != SASL_OK)
      {
	dprint (1, (debugfile, "imap_auth_sasl: error base64-encoding client response.\n"));
	goto bail;
      }
    }
    
    if (irc == IMAP_CMD_RESPOND)
    {
      strfcpy (buf + olen, "\r\n", sizeof (buf) - olen);
      mutt_socket_write (idata->conn, buf);
    }

    /* If SASL has errored out, send an abort string to the server */
    if (rc < 0)
    {
      mutt_socket_write (idata->conn, "*\r\n");
      dprint (1, (debugfile, "imap_auth_sasl: sasl_client_step error %d\n",rc));
    }
	  
    olen = 0;
  }

  while (irc != IMAP_CMD_OK)
    if ((irc = imap_cmd_step (idata)) != IMAP_CMD_CONTINUE)
      break;

  if (rc != SASL_OK)
    goto bail;

  if (imap_code (idata->buf))
  {
    mutt_sasl_setup_conn (idata->conn, saslconn);
    return IMAP_AUTH_SUCCESS;
  }

 bail:
  sasl_dispose (&saslconn);

  if (method)
  {
    dprint (2, (debugfile, "imap_auth_sasl: %s failed\n", method));
    return IMAP_AUTH_UNAVAIL;
  }

  mutt_error _("SASL authentication failed.");
  mutt_sleep(2);

  return IMAP_AUTH_FAILURE;
}
Beispiel #21
0
static int tls_check_one_certificate (const gnutls_datum_t *certdata,
                                      gnutls_certificate_status certstat,
                                      const char* hostname, int idx, int len)
{
  int certerr, savedcert;
  gnutls_x509_crt cert;
  char buf[SHORT_STRING];
  char fpbuf[SHORT_STRING];
  size_t buflen;
  char dn_common_name[SHORT_STRING];
  char dn_email[SHORT_STRING];
  char dn_organization[SHORT_STRING];
  char dn_organizational_unit[SHORT_STRING];
  char dn_locality[SHORT_STRING];
  char dn_province[SHORT_STRING];
  char dn_country[SHORT_STRING];
  time_t t;
  char datestr[30];
  MUTTMENU *menu;
  char helpstr[LONG_STRING];
  char title[STRING];
  FILE *fp;
  gnutls_datum pemdata;
  int i, row, done, ret;

  if (!tls_check_preauth (certdata, certstat, hostname, idx, &certerr,
      &savedcert))
    return 1;

  /* skip signers if insecure algorithm was used */
  if (idx && (certerr & CERTERR_INSECUREALG))
  {
    if (idx == 1)
    {
      mutt_error (_("Warning: Server certificate was signed using an insecure algorithm"));
      mutt_sleep (2);
    }
    return 0;
  }

  /* interactive check from user */
  if (gnutls_x509_crt_init (&cert) < 0)
  {
    mutt_error (_("Error initialising gnutls certificate data"));
    mutt_sleep (2);
    return 0;
  }

  if (gnutls_x509_crt_import (cert, certdata, GNUTLS_X509_FMT_DER) < 0)
  {
    mutt_error (_("Error processing certificate data"));
    mutt_sleep (2);
    gnutls_x509_crt_deinit (cert);
    return -1;
  }

  menu = mutt_new_menu (-1);
  menu->max = 25;
  menu->dialog = (char **) safe_calloc (1, menu->max * sizeof (char *));
  for (i = 0; i < menu->max; i++)
    menu->dialog[i] = (char *) safe_calloc (1, SHORT_STRING * sizeof (char));

  row = 0;
  strfcpy (menu->dialog[row], _("This certificate belongs to:"), SHORT_STRING);
  row++;

  buflen = sizeof (dn_common_name);
  if (gnutls_x509_crt_get_dn_by_oid (cert, GNUTLS_OID_X520_COMMON_NAME, 0, 0,
                                     dn_common_name, &buflen) != 0)
    dn_common_name[0] = '\0';
  buflen = sizeof (dn_email);
  if (gnutls_x509_crt_get_dn_by_oid (cert, GNUTLS_OID_PKCS9_EMAIL, 0, 0,
                                     dn_email, &buflen) != 0)
    dn_email[0] = '\0';
  buflen = sizeof (dn_organization);
  if (gnutls_x509_crt_get_dn_by_oid (cert, GNUTLS_OID_X520_ORGANIZATION_NAME, 0, 0,
                                     dn_organization, &buflen) != 0)
    dn_organization[0] = '\0';
  buflen = sizeof (dn_organizational_unit);
  if (gnutls_x509_crt_get_dn_by_oid (cert, GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME, 0, 0,
                                     dn_organizational_unit, &buflen) != 0)
    dn_organizational_unit[0] = '\0';
  buflen = sizeof (dn_locality);
  if (gnutls_x509_crt_get_dn_by_oid (cert, GNUTLS_OID_X520_LOCALITY_NAME, 0, 0,
                                     dn_locality, &buflen) != 0)
    dn_locality[0] = '\0';
  buflen = sizeof (dn_province);
  if (gnutls_x509_crt_get_dn_by_oid (cert, GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME, 0, 0,
                                     dn_province, &buflen) != 0)
    dn_province[0] = '\0';
  buflen = sizeof (dn_country);
  if (gnutls_x509_crt_get_dn_by_oid (cert, GNUTLS_OID_X520_COUNTRY_NAME, 0, 0,
                                     dn_country, &buflen) != 0)
    dn_country[0] = '\0';

  snprintf (menu->dialog[row++], SHORT_STRING, "   %s  %s", dn_common_name, dn_email);
  snprintf (menu->dialog[row++], SHORT_STRING, "   %s", dn_organization);
  snprintf (menu->dialog[row++], SHORT_STRING, "   %s", dn_organizational_unit);
  snprintf (menu->dialog[row++], SHORT_STRING, "   %s  %s  %s",
            dn_locality, dn_province, dn_country);
  row++;

  strfcpy (menu->dialog[row], _("This certificate was issued by:"), SHORT_STRING);
  row++;

  buflen = sizeof (dn_common_name);
  if (gnutls_x509_crt_get_issuer_dn_by_oid (cert, GNUTLS_OID_X520_COMMON_NAME, 0, 0,
                                            dn_common_name, &buflen) != 0)
    dn_common_name[0] = '\0';
  buflen = sizeof (dn_email);
  if (gnutls_x509_crt_get_issuer_dn_by_oid (cert, GNUTLS_OID_PKCS9_EMAIL, 0, 0,
                                            dn_email, &buflen) != 0)
    dn_email[0] = '\0';
  buflen = sizeof (dn_organization);
  if (gnutls_x509_crt_get_issuer_dn_by_oid (cert, GNUTLS_OID_X520_ORGANIZATION_NAME, 0, 0,
                                            dn_organization, &buflen) != 0)
    dn_organization[0] = '\0';
  buflen = sizeof (dn_organizational_unit);
  if (gnutls_x509_crt_get_issuer_dn_by_oid (cert, GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME, 0, 0,
                                            dn_organizational_unit, &buflen) != 0)
    dn_organizational_unit[0] = '\0';
  buflen = sizeof (dn_locality);
  if (gnutls_x509_crt_get_issuer_dn_by_oid (cert, GNUTLS_OID_X520_LOCALITY_NAME, 0, 0,
                                            dn_locality, &buflen) != 0)
    dn_locality[0] = '\0';
  buflen = sizeof (dn_province);
  if (gnutls_x509_crt_get_issuer_dn_by_oid (cert, GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME, 0, 0,
                                            dn_province, &buflen) != 0)
    dn_province[0] = '\0';
  buflen = sizeof (dn_country);
  if (gnutls_x509_crt_get_issuer_dn_by_oid (cert, GNUTLS_OID_X520_COUNTRY_NAME, 0, 0,
                                            dn_country, &buflen) != 0)
    dn_country[0] = '\0';

  snprintf (menu->dialog[row++], SHORT_STRING, "   %s  %s", dn_common_name, dn_email);
  snprintf (menu->dialog[row++], SHORT_STRING, "   %s", dn_organization);
  snprintf (menu->dialog[row++], SHORT_STRING, "   %s", dn_organizational_unit);
  snprintf (menu->dialog[row++], SHORT_STRING, "   %s  %s  %s",
            dn_locality, dn_province, dn_country);
  row++;

  snprintf (menu->dialog[row++], SHORT_STRING, _("This certificate is valid"));

  t = gnutls_x509_crt_get_activation_time (cert);
  snprintf (menu->dialog[row++], SHORT_STRING, _("   from %s"),
	    tls_make_date (t, datestr, 30));

  t = gnutls_x509_crt_get_expiration_time (cert);
  snprintf (menu->dialog[row++], SHORT_STRING, _("     to %s"),
	    tls_make_date (t, datestr, 30));

  fpbuf[0] = '\0';
  tls_fingerprint (GNUTLS_DIG_SHA, fpbuf, sizeof (fpbuf), certdata);
  snprintf (menu->dialog[row++], SHORT_STRING, _("SHA1 Fingerprint: %s"), fpbuf);
  fpbuf[0] = '\0';
  tls_fingerprint (GNUTLS_DIG_MD5, fpbuf, sizeof (fpbuf), certdata);
  snprintf (menu->dialog[row++], SHORT_STRING, _("MD5 Fingerprint: %s"), fpbuf);

  if (certerr & CERTERR_NOTYETVALID)
  {
    row++;
    strfcpy (menu->dialog[row], _("WARNING: Server certificate is not yet valid"), SHORT_STRING);
  }
  if (certerr & CERTERR_EXPIRED)
  {
    row++;
    strfcpy (menu->dialog[row], _("WARNING: Server certificate has expired"), SHORT_STRING);
  }
  if (certerr & CERTERR_REVOKED)
  {
    row++;
    strfcpy (menu->dialog[row], _("WARNING: Server certificate has been revoked"), SHORT_STRING);
  }
  if (certerr & CERTERR_HOSTNAME)
  {
    row++;
    strfcpy (menu->dialog[row], _("WARNING: Server hostname does not match certificate"), SHORT_STRING);
  }
  if (certerr & CERTERR_SIGNERNOTCA)
  {
    row++;
    strfcpy (menu->dialog[row], _("WARNING: Signer of server certificate is not a CA"), SHORT_STRING);
  }

  snprintf (title, sizeof (title),
            _("SSL Certificate check (certificate %d of %d in chain)"),
            len - idx, len);
  menu->title = title;
  /* certificates with bad dates, or that are revoked, must be
   accepted manually each and every time */
  if (SslCertFile && !savedcert
        && !(certerr & (CERTERR_EXPIRED | CERTERR_NOTYETVALID
                        | CERTERR_REVOKED)))
  {
    menu->prompt = _("(r)eject, accept (o)nce, (a)ccept always");
    menu->keys = _("roa");
  }
  else
  {
    menu->prompt = _("(r)eject, accept (o)nce");
    menu->keys = _("ro");
  }

  helpstr[0] = '\0';
  mutt_make_help (buf, sizeof (buf), _("Exit  "), MENU_GENERIC, OP_EXIT);
  safe_strcat (helpstr, sizeof (helpstr), buf);
  mutt_make_help (buf, sizeof (buf), _("Help"), MENU_GENERIC, OP_HELP);
  safe_strcat (helpstr, sizeof (helpstr), buf);
  menu->help = helpstr;

  done = 0;
  set_option (OPTUNBUFFEREDINPUT);
  while (!done)
  {
    switch (mutt_menuLoop (menu))
    {
      case -1:			/* abort */
      case OP_MAX + 1:		/* reject */
      case OP_EXIT:
        done = 1;
        break;
      case OP_MAX + 3:		/* accept always */
        done = 0;
        if ((fp = fopen (SslCertFile, "a")))
	{
	  /* save hostname if necessary */
	  if (certerr & CERTERR_HOSTNAME)
	  {
	    fprintf(fp, "#H %s %s\n", hostname, fpbuf);
	    done = 1;
	  }
	  if (certerr & CERTERR_NOTTRUSTED)
	  {
            done = 0;
	    ret = gnutls_pem_base64_encode_alloc ("CERTIFICATE", certdata,
                                                  &pemdata);
	    if (ret == 0)
	    {
	      if (fwrite (pemdata.data, pemdata.size, 1, fp) == 1)
	      {
		done = 1;
	      }
              gnutls_free (pemdata.data);
	    }
	  }
	  safe_fclose (&fp);
	}
	if (!done)
        {
	  mutt_error (_("Warning: Couldn't save certificate"));
	  mutt_sleep (2);
	}
	else
        {
	  mutt_message (_("Certificate saved"));
	  mutt_sleep (0);
	}
        /* fall through */
      case OP_MAX + 2:		/* accept once */
        done = 2;
        break;
    }
  }
  unset_option (OPTUNBUFFEREDINPUT);
  mutt_menuDestroy (&menu);
  gnutls_x509_crt_deinit (cert);

  return (done == 2);
}
Beispiel #22
0
/* tls_negotiate: After TLS state has been initialised, attempt to negotiate
 *   TLS over the wire, including certificate checks. */
static int tls_negotiate (CONNECTION * conn)
{
  tlssockdata *data;
  int err;
  size_t nproto = 0; /* number of tls/ssl protocols */

  data = (tlssockdata *) safe_calloc (1, sizeof (tlssockdata));
  conn->sockdata = data;
  err = gnutls_certificate_allocate_credentials (&data->xcred);
  if (err < 0)
  {
    FREE(&conn->sockdata);
    mutt_error ("gnutls_certificate_allocate_credentials: %s", gnutls_strerror(err));
    mutt_sleep (2);
    return -1;
  }

  gnutls_certificate_set_x509_trust_file (data->xcred, SslCertFile,
					  GNUTLS_X509_FMT_PEM);
  /* ignore errors, maybe file doesn't exist yet */

  if (SslCACertFile)
  {
    gnutls_certificate_set_x509_trust_file (data->xcred, SslCACertFile,
                                            GNUTLS_X509_FMT_PEM);
  }

  if (SslClientCert)
  {
    dprint (2, (debugfile, "Using client certificate %s\n", SslClientCert));
    gnutls_certificate_set_x509_key_file (data->xcred, SslClientCert,
                                          SslClientCert, GNUTLS_X509_FMT_PEM);
  }

#if HAVE_DECL_GNUTLS_VERIFY_DISABLE_TIME_CHECKS
  /* disable checking certificate activation/expiration times
     in gnutls, we do the checks ourselves */
  gnutls_certificate_set_verify_flags(data->xcred, GNUTLS_VERIFY_DISABLE_TIME_CHECKS);
#endif

  if ((err = gnutls_init(&data->state, GNUTLS_CLIENT)))
  {
    mutt_error ("gnutls_handshake: %s", gnutls_strerror(err));
    mutt_sleep (2);
    goto fail;
  }

  /* set socket */
  gnutls_transport_set_ptr (data->state, (gnutls_transport_ptr)conn->fd);

  if (option(OPTTLSV1_2))
    protocol_priority[nproto++] = GNUTLS_TLS1_2;
  if (option(OPTTLSV1_1))
    protocol_priority[nproto++] = GNUTLS_TLS1_1;
  if (option(OPTTLSV1))
    protocol_priority[nproto++] = GNUTLS_TLS1;
  if (option(OPTSSLV3))
    protocol_priority[nproto++] = GNUTLS_SSL3;
  protocol_priority[nproto] = 0;

  /* disable TLS/SSL protocols as needed */
  if (nproto == 0)
  {
    mutt_error (_("All available protocols for TLS/SSL connection disabled"));
    goto fail;
  }
  /*
  else
    use the list set above
  */

  /* We use default priorities (see gnutls documentation),
     except for protocol version */
  gnutls_set_default_priority (data->state);
  gnutls_protocol_set_priority (data->state, protocol_priority);

  if (SslDHPrimeBits > 0)
  {
    gnutls_dh_set_prime_bits (data->state, SslDHPrimeBits);
  }

/*
  gnutls_set_cred (data->state, GNUTLS_ANON, NULL);
*/

  gnutls_credentials_set (data->state, GNUTLS_CRD_CERTIFICATE, data->xcred);

  err = gnutls_handshake(data->state);

  while (err == GNUTLS_E_AGAIN || err == GNUTLS_E_INTERRUPTED)
  {
    err = gnutls_handshake(data->state);
  }
  if (err < 0) {
    if (err == GNUTLS_E_FATAL_ALERT_RECEIVED)
    {
      mutt_error("gnutls_handshake: %s(%s)", gnutls_strerror(err),
		 gnutls_alert_get_name(gnutls_alert_get(data->state)));
    }
    else
    {
      mutt_error("gnutls_handshake: %s", gnutls_strerror(err));
    }
    mutt_sleep (2);
    goto fail;
  }

  if (!tls_check_certificate(conn))
    goto fail;

  /* set Security Strength Factor (SSF) for SASL */
  /* NB: gnutls_cipher_get_key_size() returns key length in bytes */
  conn->ssf = gnutls_cipher_get_key_size (gnutls_cipher_get (data->state)) * 8;

  tls_get_client_cert (conn);

  if (!option(OPTNOCURSES)) {
    mutt_message (_("SSL/TLS connection using %s (%s/%s/%s)"),
                  gnutls_protocol_get_name (gnutls_protocol_get_version (data->state)),
                  gnutls_kx_get_name (gnutls_kx_get (data->state)),
                  gnutls_cipher_get_name (gnutls_cipher_get (data->state)),
                  gnutls_mac_get_name (gnutls_mac_get (data->state)));
    mutt_sleep (0);
  }

  return 0;

 fail:
  gnutls_certificate_free_credentials (data->xcred);
  gnutls_deinit (data->state);
  FREE(&conn->sockdata);
  return -1;
}
Beispiel #23
0
int mutt_slow_close_compressed (CONTEXT * ctx)
{
    FILE *fp;
    const char *append;
    char *cmd;
    COMPRESS_INFO *ci = (COMPRESS_INFO *) ctx->compressinfo;

    debug_print (2, ("called on '%s'\n", ctx->path));

    if (!(ctx->append && ((append = get_append_command (ctx->realpath, ctx))
                          || (append = ci->close)))) {
        /* if we can not or should not append,
                                         * we only have to remove the compressed info, because sync was already
                                         * called
                                         */
        mutt_fast_close_compressed (ctx);
        return (0);
    }

    if (ctx->fp)
        fclose (ctx->fp);
    ctx->fp = NULL;

    if (!ctx->quiet) {
        if (append == ci->close)
            mutt_message (_("Compressing %s..."), ctx->realpath);
        else
            mutt_message (_("Compressed-appending to %s..."), ctx->realpath);
    }

    cmd = get_compression_cmd (append, ctx);
    if (cmd == NULL)
        return (-1);

    if ((fp = fopen (ctx->realpath, "a")) == NULL) {
        mutt_perror (ctx->realpath);
        mem_free (&cmd);
        return (-1);
    }
    mutt_block_signals ();
    if (mbox_lock_compressed (ctx, fp, 1, 1) == -1) {
        fclose (fp);
        mutt_unblock_signals ();
        mutt_error _("Unable to lock mailbox!");

        mem_free (&cmd);
        return (-1);
    }

    debug_print (2, ("CompressCmd: '%s'\n", cmd));

    endwin ();
    fflush (stdout);

    if (append == ci->close)
        sprintf (echo_cmd, _("echo Compressing %s..."), ctx->realpath);
    else
        sprintf (echo_cmd, _("echo Compressed-appending to %s..."),
                 ctx->realpath);
    mutt_system (echo_cmd);

    if (mutt_system (cmd)) {
        mutt_any_key_to_continue (NULL);
        mutt_error (_
                    (" %s: Error compressing mailbox!  Uncompressed one kept!\n"),
                    ctx->path);
        mem_free (&cmd);
        mbox_unlock_compressed (ctx, fp);
        mutt_unblock_signals ();
        fclose (fp);
        return (-1);
    }

    mbox_unlock_compressed (ctx, fp);
    mutt_unblock_signals ();
    fclose (fp);
    remove_file (ctx);
    restore_path (ctx);
    mem_free (&cmd);
    mem_free (&ctx->compressinfo);

    return (0);
}
Beispiel #24
0
int mutt_open_read_compressed (CONTEXT * ctx)
{
    char *cmd;
    FILE *fp;
    int rc;

    COMPRESS_INFO *ci = set_compress_info (ctx);

    if (!ci->open) {
        ctx->magic = 0;
        mem_free (ctx->compressinfo);
        return (-1);
    }
    if (!ci->close || access (ctx->path, W_OK) != 0)
        ctx->readonly = 1;

    set_path (ctx);
    store_size (ctx);

    if (!ctx->quiet)
        mutt_message (_("Decompressing %s..."), ctx->realpath);

    cmd = get_compression_cmd (ci->open, ctx);
    if (cmd == NULL)
        return (-1);
    debug_print (2, ("DecompressCmd: '%s'\n", cmd));

    if ((fp = fopen (ctx->realpath, "r")) == NULL) {
        mutt_perror (ctx->realpath);
        mem_free (&cmd);
        return (-1);
    }
    mutt_block_signals ();
    if (mbox_lock_compressed (ctx, fp, 0, 1) == -1) {
        fclose (fp);
        mutt_unblock_signals ();
        mutt_error _("Unable to lock mailbox!");

        mem_free (&cmd);
        return (-1);
    }

    endwin ();
    fflush (stdout);
    sprintf (echo_cmd, _("echo Decompressing %s..."), ctx->realpath);
    mutt_system (echo_cmd);
    rc = mutt_system (cmd);
    mbox_unlock_compressed (ctx, fp);
    mutt_unblock_signals ();
    fclose (fp);

    if (rc) {
        mutt_any_key_to_continue (NULL);
        ctx->magic = 0;
        mem_free (ctx->compressinfo);
        mutt_error (_("Error executing: %s : unable to open the mailbox!\n"),
                    cmd);
    }
    mem_free (&cmd);
    if (rc)
        return (-1);

    if (mutt_check_mailbox_compressed (ctx))
        return (-1);

    ctx->magic = mx_get_magic (ctx->path);

    return (0);
}
Beispiel #25
0
static int interactive_check_cert (X509 *cert, int idx, int len)
{
        static const char * const part[] =
                {"/CN=", "/Email=", "/O=", "/OU=", "/L=", "/ST=", "/C="};
        char helpstr[LONG_STRING];
        char buf[STRING];
        char title[STRING];
        MUTTMENU *menu = mutt_new_menu (-1);
        int done, row, i;
        FILE *fp;
        char *name = NULL, *c;

        dprint (2, (debugfile, "interactive_check_cert: %s\n", cert->name));

        menu->max = 19;
        menu->dialog = (char **) safe_calloc (1, menu->max * sizeof (char *));
        for (i = 0; i < menu->max; i++)
                menu->dialog[i] = (char *) safe_calloc (1, SHORT_STRING * sizeof (char));

        row = 0;
        strfcpy (menu->dialog[row], _("This certificate belongs to:"), SHORT_STRING);
        row++;
        name = X509_NAME_oneline (X509_get_subject_name (cert),
                buf, sizeof (buf));
        dprint (2, (debugfile, "oneline: %s\n", name));

        for (i = 0; i < 5; i++) {
                c = x509_get_part (name, part[i]);
                snprintf (menu->dialog[row++], SHORT_STRING, "   %s", c);
        }

        row++;
        strfcpy (menu->dialog[row], _("This certificate was issued by:"), SHORT_STRING);
        row++;
        name = X509_NAME_oneline (X509_get_issuer_name (cert),
                buf, sizeof (buf));
        for (i = 0; i < 5; i++) {
                c = x509_get_part (name, part[i]);
                snprintf (menu->dialog[row++], SHORT_STRING, "   %s", c);
        }

        row++;
        snprintf (menu->dialog[row++], SHORT_STRING, _("This certificate is valid"));
        snprintf (menu->dialog[row++], SHORT_STRING, _("   from %s"),
                asn1time_to_string (X509_get_notBefore (cert)));
        snprintf (menu->dialog[row++], SHORT_STRING, _("     to %s"),
                asn1time_to_string (X509_get_notAfter (cert)));

        row++;
        buf[0] = '\0';
        x509_fingerprint (buf, sizeof (buf), cert);
        snprintf (menu->dialog[row++], SHORT_STRING, _("Fingerprint: %s"), buf);

        snprintf (title, sizeof (title),
                _("SSL Certificate check (certificate %d of %d in chain)"),
                len - idx, len);
        menu->title = title;
        if (SslCertFile
                && (option (OPTSSLVERIFYDATES) == M_NO
                || (X509_cmp_current_time (X509_get_notAfter (cert)) >= 0
        && X509_cmp_current_time (X509_get_notBefore (cert)) < 0))) {
                menu->prompt = _("(r)eject, accept (o)nce, (a)ccept always");
                menu->keys = _("roa");
        }
        else {
                menu->prompt = _("(r)eject, accept (o)nce");
                menu->keys = _("ro");
        }

        helpstr[0] = '\0';
        mutt_make_help (buf, sizeof (buf), _("Exit  "), MENU_GENERIC, OP_EXIT);
        safe_strcat (helpstr, sizeof (helpstr), buf);
        mutt_make_help (buf, sizeof (buf), _("Help"), MENU_GENERIC, OP_HELP);
        safe_strcat (helpstr, sizeof (helpstr), buf);
        menu->help = helpstr;

        done = 0;
        set_option(OPTUNBUFFEREDINPUT);
        while (!done) {
                switch (mutt_menuLoop (menu)) {
                        case -1:                  /* abort */
                        case OP_MAX + 1:          /* reject */
                        case OP_EXIT:
                                done = 1;
                                break;
                        case OP_MAX + 3:          /* accept always */
                                done = 0;
                                if ((fp = fopen (SslCertFile, "a"))) {
                                        if (PEM_write_X509 (fp, cert))
                                                done = 1;
                                        safe_fclose (&fp);
                                }
                                if (!done) {
                                        mutt_error (_("Warning: Couldn't save certificate"));
                                        mutt_sleep (2);
                                }
                                else {
                                        mutt_message (_("Certificate saved"));
                                        mutt_sleep (0);
                                }
/* fall through */
                        case OP_MAX + 2:          /* accept once */
                                done = 2;
                                ssl_cache_trusted_cert (cert);
                                break;
                }
        }
        unset_option(OPTUNBUFFEREDINPUT);
        mutt_menuDestroy (&menu);
        dprint (2, (debugfile, "ssl interactive_check_cert: done=%d\n", done));
        return (done == 2);
}
Beispiel #26
0
pgp_key_t pgp_getkeybyaddr (ADDRESS * a, short abilities, pgp_ring_t keyring,
                            int oppenc_mode)
{
  ADDRESS *r, *p;
  LIST *hints = NULL;

  int multi   = 0;
  int match;

  pgp_key_t keys, k, kn;
  pgp_key_t the_strong_valid_key = NULL;
  pgp_key_t a_valid_addrmatch_key = NULL;
  pgp_key_t matches = NULL;
  pgp_key_t *last = &matches;
  pgp_uid_t *q;

  if (a && a->mailbox)
    hints = pgp_add_string_to_hints (hints, a->mailbox);
  if (a && a->personal)
    hints = pgp_add_string_to_hints (hints, a->personal);

  if (! oppenc_mode )
    mutt_message (_("Looking for keys matching \"%s\"..."), a->mailbox);
  keys = pgp_get_candidates (keyring, hints);

  mutt_free_list (&hints);

  if (!keys)
    return NULL;

  dprint (5, (debugfile, "pgp_getkeybyaddr: looking for %s <%s>.",
	      a->personal, a->mailbox));


  for (k = keys; k; k = kn)
  {
    kn = k->next;

    dprint (5, (debugfile, "  looking at key: %s\n",
		pgp_keyid (k)));

    if (abilities && !(k->flags & abilities))
    {
      dprint (5, (debugfile, "  insufficient abilities: Has %x, want %x\n",
		  k->flags, abilities));
      continue;
    }

    match                = 0;   /* any match 		  */

    for (q = k->address; q; q = q->next)
    {
      r = rfc822_parse_adrlist (NULL, NONULL (q->addr));

      for (p = r; p; p = p->next)
      {
	int validity = pgp_id_matches_addr (a, p, q);

	if (validity & PGP_KV_MATCH)	/* something matches */
	  match = 1;

        if ((validity & PGP_KV_VALID)
            && (validity & PGP_KV_ADDR))
        {
          if (validity & PGP_KV_STRONGID)
          {
            if (the_strong_valid_key && the_strong_valid_key != k)
              multi = 1;
            the_strong_valid_key = k;
          }
          else
          {
            a_valid_addrmatch_key = k;
          }
        }
      }

      rfc822_free_address (&r);
    }

    if (match)
    {
      *last  = pgp_principal_key (k);
      kn     = pgp_remove_key (&keys, *last);
      last   = pgp_get_lastp (k);
    }
  }

  pgp_free_key (&keys);

  if (matches)
  {
    if (oppenc_mode)
    {
      if (the_strong_valid_key)
      {
        pgp_remove_key (&matches, the_strong_valid_key);
        k = the_strong_valid_key;
      }
      else if (a_valid_addrmatch_key)
      {
        pgp_remove_key (&matches, a_valid_addrmatch_key);
        k = a_valid_addrmatch_key;
      }
      else
        k = NULL;
    }
    else if (the_strong_valid_key && !multi)
    {
      /*
       * There was precisely one strong match on a valid ID.
       * 
       * Proceed without asking the user.
       */
      pgp_remove_key (&matches, the_strong_valid_key);
      k = the_strong_valid_key;
    }
    else 
    {
      /* 
       * Else: Ask the user.
       */
      if ((k = pgp_select_key (matches, a, NULL)))
	pgp_remove_key (&matches, k);
    }

    pgp_free_key (&matches);

    return k;
  }

  return NULL;
}
Beispiel #27
0
static pgp_key_t pgp_select_key (pgp_key_t keys,
                                 ADDRESS * p, const char *s)
{
  int keymax;
  pgp_uid_t **KeyTable;
  MUTTMENU *menu;
  int i, done = 0;
  char helpstr[LONG_STRING], buf[LONG_STRING], tmpbuf[STRING];
  char cmd[LONG_STRING], tempfile[_POSIX_PATH_MAX];
  FILE *fp, *devnull;
  pid_t thepid;
  pgp_key_t kp;
  pgp_uid_t *a;
  int (*f) (const void *, const void *);

  int unusable = 0;

  keymax = 0;
  KeyTable = NULL;

  for (i = 0, kp = keys; kp; kp = kp->next)
  {
    if (!option (OPTPGPSHOWUNUSABLE) && (kp->flags & KEYFLAG_CANTUSE))
    {
      unusable = 1;
      continue;
    }

    for (a = kp->address; a; a = a->next)
    {
      if (!option (OPTPGPSHOWUNUSABLE) && (a->flags & KEYFLAG_CANTUSE))
      {
	unusable = 1;
	continue;
      }

      if (i == keymax)
      {
	keymax += 5;
	safe_realloc (&KeyTable, sizeof (pgp_uid_t *) * keymax);
      }

      KeyTable[i++] = a;
    }
  }

  if (!i && unusable)
  {
    mutt_error _("All matching keys are expired, revoked, or disabled.");
    mutt_sleep (1);
    return NULL;
  }

  switch (PgpSortKeys & SORT_MASK)
  {
    case SORT_DATE:
      f = pgp_compare_date;
      break;
    case SORT_KEYID:
      f = pgp_compare_keyid;
      break;
    case SORT_ADDRESS:
      f = pgp_compare_address;
      break;
    case SORT_TRUST:
    default:
      f = pgp_compare_trust;
      break;
  }
  qsort (KeyTable, i, sizeof (pgp_uid_t *), f);

  helpstr[0] = 0;
  mutt_make_help (buf, sizeof (buf), _("Exit  "), MENU_PGP, OP_EXIT);
  strcat (helpstr, buf);	/* __STRCAT_CHECKED__ */
  mutt_make_help (buf, sizeof (buf), _("Select  "), MENU_PGP,
		  OP_GENERIC_SELECT_ENTRY);
  strcat (helpstr, buf);	/* __STRCAT_CHECKED__ */
  mutt_make_help (buf, sizeof (buf), _("Check key  "), MENU_PGP, OP_VERIFY_KEY);
  strcat (helpstr, buf);	/* __STRCAT_CHECKED__ */
  mutt_make_help (buf, sizeof (buf), _("Help"), MENU_PGP, OP_HELP);
  strcat (helpstr, buf);	/* __STRCAT_CHECKED__ */

  menu = mutt_new_menu (MENU_PGP);
  menu->max = i;
  menu->make_entry = pgp_entry;
  menu->help = helpstr;
  menu->data = KeyTable;

  if (p)
    snprintf (buf, sizeof (buf), _("PGP keys matching <%s>."), p->mailbox);
  else
    snprintf (buf, sizeof (buf), _("PGP keys matching \"%s\"."), s);


  menu->title = buf;

  kp = NULL;

  mutt_clear_error ();

  while (!done)
  {
    switch (mutt_menuLoop (menu))
    {

    case OP_VERIFY_KEY:

      mutt_mktemp (tempfile, sizeof (tempfile));
      if ((devnull = fopen ("/dev/null", "w")) == NULL)	/* __FOPEN_CHECKED__ */
      {
	mutt_perror _("Can't open /dev/null");
	break;
      }
      if ((fp = safe_fopen (tempfile, "w")) == NULL)
      {
	safe_fclose (&devnull);
	mutt_perror _("Can't create temporary file");
	break;
      }

      mutt_message _("Invoking PGP...");

      snprintf (tmpbuf, sizeof (tmpbuf), "0x%s",
          pgp_fpr_or_lkeyid (pgp_principal_key (KeyTable[menu->current]->parent)));

      if ((thepid = pgp_invoke_verify_key (NULL, NULL, NULL, -1,
		    fileno (fp), fileno (devnull), tmpbuf)) == -1)
      {
	mutt_perror _("Can't create filter");
	unlink (tempfile);
	safe_fclose (&fp);
	safe_fclose (&devnull);
      }

      mutt_wait_filter (thepid);
      safe_fclose (&fp);
      safe_fclose (&devnull);
      mutt_clear_error ();
      snprintf (cmd, sizeof (cmd), _("Key ID: 0x%s"), 
		pgp_keyid (pgp_principal_key (KeyTable[menu->current]->parent)));
      mutt_do_pager (cmd, tempfile, 0, NULL);
      menu->redraw = REDRAW_FULL;

      break;

    case OP_VIEW_ID:

      mutt_message ("%s", NONULL (KeyTable[menu->current]->addr));
      break;

    case OP_GENERIC_SELECT_ENTRY:


      /* XXX make error reporting more verbose */

      if (option (OPTPGPCHECKTRUST))
	if (!pgp_key_is_valid (KeyTable[menu->current]->parent))
	{
	  mutt_error _("This key can't be used: expired/disabled/revoked.");
	  break;
	}

      if (option (OPTPGPCHECKTRUST) &&
	  (!pgp_id_is_valid (KeyTable[menu->current])
	   || !pgp_id_is_strong (KeyTable[menu->current])))
      {
	char *s = "";
	char buff[LONG_STRING];
	
	if (KeyTable[menu->current]->flags & KEYFLAG_CANTUSE)
	  s = N_("ID is expired/disabled/revoked.");
	else switch (KeyTable[menu->current]->trust & 0x03)
	{
	  case 0:
	    s = N_("ID has undefined validity.");
	    break;
	  case 1:
	    s = N_("ID is not valid.");
	    break;
	  case 2:
	    s = N_("ID is only marginally valid.");
	    break;
	}

	snprintf (buff, sizeof (buff), _("%s Do you really want to use the key?"),
		  _(s));

	if (mutt_yesorno (buff, M_NO) != M_YES)
	{
	  mutt_clear_error ();
	  break;
	}
      }

# if 0
      kp = pgp_principal_key (KeyTable[menu->current]->parent);
# else
      kp = KeyTable[menu->current]->parent;
# endif
      done = 1;
      break;

    case OP_EXIT:

      kp = NULL;
      done = 1;
      break;
    }
  }

  mutt_menuDestroy (&menu);
  FREE (&KeyTable);

  set_option (OPTNEEDREDRAW);

  return (kp);
}
Beispiel #28
0
pgp_key_t pgp_getkeybystr (char *p, short abilities, pgp_ring_t keyring)
{
  LIST *hints = NULL;
  pgp_key_t keys;
  pgp_key_t matches = NULL;
  pgp_key_t *last = &matches;
  pgp_key_t k, kn;
  pgp_uid_t *a;
  short match;
  size_t l;
  const char *ps, *pl;

  if ((l = mutt_strlen (p)) && p[l-1] == '!')
    p[l-1] = 0;

  mutt_message (_("Looking for keys matching \"%s\"..."), p);

  hints = pgp_add_string_to_hints (hints, p);
  keys = pgp_get_candidates (keyring, hints);
  mutt_free_list (&hints);

  if (!keys)
    goto out;

  /* User input may be short or long key ID, independent of OPTPGPLONGIDS.
   * pgp_key_t->keyid should always contain a long key ID without 0x.
   * Strip leading "0x" before loops so it doesn't have to be done over and
   * over again, and prepare pl and ps to simplify logic in the loop's inner
   * condition.
   */
  pl = (!mutt_strncasecmp (p, "0x", 2) ? p + 2 : p);
  ps = (mutt_strlen (pl) == 16 ? pl + 8 : pl);

  for (k = keys; k; k = kn)
  {
    kn = k->next;
    if (abilities && !(k->flags & abilities))
      continue;

    /* This shouldn't happen, but keys without any addresses aren't selectable
     * in pgp_select_key().
     */
    if (!k->address)
      continue;

    match = 0;

    dprint (5, (debugfile, "pgp_getkeybystr: matching \"%s\" against key %s:\n",
                p, pgp_long_keyid (k)));

    /* If ps != pl it means a long ID (or name of 16 characters) was given, do
     * not attempt to match short IDs then. Also, it is unnecessary to try to
     * match pl against long IDs if ps == pl as pl could not be a long ID. */
    if (!*p ||
        (ps != pl && mutt_strcasecmp (pl, pgp_long_keyid (k)) == 0) ||
        (ps == pl && mutt_strcasecmp (ps, pgp_short_keyid (k)) == 0))
    {
      dprint (5, (debugfile, "\t\tmatch.\n"));
      match = 1;
    }
    else
    {
      for (a = k->address; a; a = a->next)
      {
        dprint (5, (debugfile, "pgp_getkeybystr: matching \"%s\" against key %s, \"%s\":\n",
                    p, pgp_long_keyid (k), NONULL (a->addr)));
        if (mutt_stristr (a->addr, p))
        {
          dprint (5, (debugfile, "\t\tmatch.\n"));
          match = 1;
          break;
        }
      }
    }

    if (match)
    {
      *last = pgp_principal_key (k);
      kn    = pgp_remove_key (&keys, *last);
      last  = pgp_get_lastp (k);
    }
  }

  pgp_free_key (&keys);

  if (matches)
  {
    if ((k = pgp_select_key (matches, NULL, p)))
      pgp_remove_key (&matches, k);

    pgp_free_key (&matches);
    if (l && !p[l-1])
      p[l-1] = '!';
    return k;
  }

out:
  if (l && !p[l-1])
    p[l-1] = '!';
  return NULL;
}
Beispiel #29
0
pgp_key_t pgp_getkeybystr (char *p, short abilities, pgp_ring_t keyring)
{
  LIST *hints = NULL;
  pgp_key_t keys;
  pgp_key_t matches = NULL;
  pgp_key_t *last = &matches;
  pgp_key_t k, kn;
  pgp_uid_t *a;
  short match;
  size_t l;
  const char *ps, *pl, *pfcopy, *phint;

  if ((l = mutt_strlen (p)) && p[l-1] == '!')
    p[l-1] = 0;

  mutt_message (_("Looking for keys matching \"%s\"..."), p);

  pfcopy = crypt_get_fingerprint_or_id (p, &phint, &pl, &ps);
  hints = pgp_add_string_to_hints (hints, phint);
  keys = pgp_get_candidates (keyring, hints);
  mutt_free_list (&hints);

  if (!keys)
    goto out;

  for (k = keys; k; k = kn)
  {
    kn = k->next;
    if (abilities && !(k->flags & abilities))
      continue;

    /* This shouldn't happen, but keys without any addresses aren't selectable
     * in pgp_select_key().
     */
    if (!k->address)
      continue;

    match = 0;

    dprint (5, (debugfile, "pgp_getkeybystr: matching \"%s\" against key %s:\n",
                p, pgp_long_keyid (k)));

    if (!*p ||
        (pfcopy && mutt_strcasecmp (pfcopy, k->fingerprint) == 0) ||
        (pl && mutt_strcasecmp (pl, pgp_long_keyid (k)) == 0) ||
        (ps && mutt_strcasecmp (ps, pgp_short_keyid (k)) == 0))
    {
      dprint (5, (debugfile, "\t\tmatch.\n"));
      match = 1;
    }
    else
    {
      for (a = k->address; a; a = a->next)
      {
        dprint (5, (debugfile, "pgp_getkeybystr: matching \"%s\" against key %s, \"%s\":\n",
                    p, pgp_long_keyid (k), NONULL (a->addr)));
        if (mutt_stristr (a->addr, p))
        {
          dprint (5, (debugfile, "\t\tmatch.\n"));
          match = 1;
          break;
        }
      }
    }

    if (match)
    {
      *last = pgp_principal_key (k);
      kn    = pgp_remove_key (&keys, *last);
      last  = pgp_get_lastp (k);
    }
  }

  pgp_free_key (&keys);

  if (matches)
  {
    if ((k = pgp_select_key (matches, NULL, p)))
      pgp_remove_key (&matches, k);

    pgp_free_key (&matches);
    FREE (&pfcopy);
    if (l && !p[l-1])
      p[l-1] = '!';
    return k;
  }

out:
  FREE (&pfcopy);
  if (l && !p[l-1])
    p[l-1] = '!';
  return NULL;
}
Beispiel #30
0
int mutt_is_application_smime (BODY *m)
{
  char *t=NULL;
  int len, complain=0;

  if(!m)
    return 0;

  if ((m->type & TYPEAPPLICATION) && m->subtype)
  {
    /* S/MIME MIME types don't need x- anymore, see RFC2311 */
    if (!ascii_strcasecmp (m->subtype, "x-pkcs7-mime") ||
	!ascii_strcasecmp (m->subtype, "pkcs7-mime"))
    {
      if ((t = mutt_get_parameter ("smime-type", m->parameter)))
      {
	if (!ascii_strcasecmp (t, "enveloped-data"))
	  return SMIMEENCRYPT;
	else if (!ascii_strcasecmp (t, "signed-data"))
	  return (SMIMESIGN|SMIMEOPAQUE);
	else return 0;
      }
      /* Netscape 4.7 uses 
       * Content-Description: S/MIME Encrypted Message
       * instead of Content-Type parameter
       */
      if (!ascii_strcasecmp (m->description, "S/MIME Encrypted Message"))
	return SMIMEENCRYPT;
      complain = 1;
    }
    else if (ascii_strcasecmp (m->subtype, "octet-stream"))
      return 0;

    t = mutt_get_parameter ("name", m->parameter);

    if (!t) t = m->d_filename;
    if (!t) t = m->filename;
    if (!t) 
    {
      if (complain)
	mutt_message (_("S/MIME messages with no hints on content are unsupported."));
      return 0;
    }

    /* no .p7c, .p10 support yet. */

    len = mutt_strlen (t) - 4;
    if (len > 0 && *(t+len) == '.')
    {
      len++;
      if (!ascii_strcasecmp ((t+len), "p7m"))
#if 0
       return SMIMEENCRYPT;
#else
      /* Not sure if this is the correct thing to do, but 
         it's required for compatibility with Outlook */
       return (SMIMESIGN|SMIMEOPAQUE);
#endif
      else if (!ascii_strcasecmp ((t+len), "p7s"))
	return (SMIMESIGN|SMIMEOPAQUE);
    }