Esempio n. 1
0
/**
 * tls_set_priority - Set TLS algorithm priorities
 * @param data TLS socket data
 * @retval  0 Success
 * @retval -1 Error
 */
static int tls_set_priority(struct TlsSockData *data)
{
  size_t nproto = 4;
  size_t priority_size;

  priority_size = mutt_str_strlen(C_SslCiphers) + 128;
  char *priority = mutt_mem_malloc(priority_size);

  priority[0] = '\0';
  if (C_SslCiphers)
    mutt_str_strcat(priority, priority_size, C_SslCiphers);
  else
    mutt_str_strcat(priority, priority_size, "NORMAL");

  if (!C_SslUseTlsv12)
  {
    nproto--;
    mutt_str_strcat(priority, priority_size, ":-VERS-TLS1.2");
  }
  if (!C_SslUseTlsv11)
  {
    nproto--;
    mutt_str_strcat(priority, priority_size, ":-VERS-TLS1.1");
  }
  if (!C_SslUseTlsv1)
  {
    nproto--;
    mutt_str_strcat(priority, priority_size, ":-VERS-TLS1.0");
  }
  if (!C_SslUseSslv3)
  {
    nproto--;
    mutt_str_strcat(priority, priority_size, ":-VERS-SSL3.0");
  }

  if (nproto == 0)
  {
    mutt_error(_("All available protocols for TLS/SSL connection disabled"));
    FREE(&priority);
    return -1;
  }

  int err = gnutls_priority_set_direct(data->state, priority, NULL);
  if (err < 0)
  {
    mutt_error("gnutls_priority_set_direct(%s): %s", priority, gnutls_strerror(err));
    FREE(&priority);
    return -1;
  }

  FREE(&priority);
  return 0;
}
Esempio n. 2
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;
}
Esempio n. 3
0
/**
 * mutt_enter_fname_full - Ask the user to select a file
 * @param[in]  prompt   Prompt
 * @param[in]  buf      Buffer for the result
 * @param[in]  buflen   Length of the buffer
 * @param[in]  mailbox  If true, select mailboxes
 * @param[in]  multiple Allow multiple selections
 * @param[out] files    List of files selected
 * @param[out] numfiles Number of files selected
 * @param[in]  flags    Flags, see #SelectFileFlags
 * @retval  0 Success
 * @retval -1 Error
 */
int mutt_enter_fname_full(const char *prompt, char *buf, size_t buflen, bool mailbox,
                          bool multiple, char ***files, int *numfiles, SelectFileFlags flags)
{
  struct Event ch;

  SETCOLOR(MT_COLOR_PROMPT);
  mutt_window_mvaddstr(MuttMessageWindow, 0, 0, (char *) prompt);
  addstr(_(" ('?' for list): "));
  NORMAL_COLOR;
  if (buf[0] != '\0')
    addstr(buf);
  mutt_window_clrtoeol(MuttMessageWindow);
  mutt_refresh();

  do
  {
    ch = mutt_getch();
  } while (ch.ch == -2);
  if (ch.ch < 0)
  {
    mutt_window_clearline(MuttMessageWindow, 0);
    return -1;
  }
  else if (ch.ch == '?')
  {
    mutt_refresh();
    buf[0] = '\0';

    if (!flags)
      flags = MUTT_SEL_FOLDER;
    if (multiple)
      flags |= MUTT_SEL_MULTI;
    if (mailbox)
      flags |= MUTT_SEL_MAILBOX;
    mutt_select_file(buf, buflen, flags, files, numfiles);
  }
  else
  {
    char *pc = mutt_mem_malloc(mutt_str_strlen(prompt) + 3);

    sprintf(pc, "%s: ", prompt);
    mutt_unget_event(ch.op ? 0 : ch.ch, ch.op ? ch.op : 0);
    if (mutt_get_field_full(pc, buf, buflen, (mailbox ? MUTT_EFILE : MUTT_FILE) | MUTT_CLEAR,
                            multiple, files, numfiles) != 0)
    {
      buf[0] = '\0';
    }
    FREE(&pc);
  }

  return 0;
}
Esempio n. 4
0
File: ssl.c Progetto: darnir/neomutt
/**
 * ssl_dprint_err_stack - Dump the SSL error stack
 */
static void ssl_dprint_err_stack(void)
{
  BIO *bio = NULL;
  char *buf = NULL;
  long buflen;
  char *output = NULL;

  bio = BIO_new(BIO_s_mem());
  if (!bio)
    return;
  ERR_print_errors(bio);
  buflen = BIO_get_mem_data(bio, &buf);
  if (buflen > 0)
  {
    output = mutt_mem_malloc(buflen + 1);
    memcpy(output, buf, buflen);
    output[buflen] = '\0';
    mutt_debug(LL_DEBUG1, "SSL error stack: %s\n", output);
    FREE(&output);
  }
  BIO_free(bio);
}
Esempio n. 5
0
File: set.c Progetto: kdave/neomutt
/**
 * cs_new - Create a new Config Set
 * @param size Number of expected config items
 * @retval ptr New ConfigSet object
 */
struct ConfigSet *cs_new(size_t size)
{
  struct ConfigSet *cs = mutt_mem_malloc(sizeof(*cs));
  cs_init(cs, size);
  return cs;
}
Esempio n. 6
0
File: ssl.c Progetto: darnir/neomutt
/**
 * check_host - Check the host on the certificate
 * @param x509cert Certificate
 * @param hostname Hostname
 * @param err      Buffer for error message
 * @param errlen   Length of buffer
 * @retval 1 Hostname matches the certificate
 * @retval 0 Error
 */
static int check_host(X509 *x509cert, const char *hostname, char *err, size_t errlen)
{
  int rc = 0;
  /* hostname in ASCII format: */
  char *hostname_ascii = NULL;
  /* needed to get the common name: */
  X509_NAME *x509_subject = NULL;
  char *buf = NULL;
  int bufsize;
  /* needed to get the DNS subjectAltNames: */
  STACK_OF(GENERAL_NAME) * subj_alt_names;
  int subj_alt_names_count;
  GENERAL_NAME *subj_alt_name = NULL;
  /* did we find a name matching hostname? */
  bool match_found;

  /* Check if 'hostname' matches the one of the subjectAltName extensions of
   * type DNS or the Common Name (CN). */

#ifdef HAVE_LIBIDN
  if (mutt_idna_to_ascii_lz(hostname, &hostname_ascii, 0) != 0)
  {
    hostname_ascii = mutt_str_strdup(hostname);
  }
#else
  hostname_ascii = mutt_str_strdup(hostname);
#endif

  /* Try the DNS subjectAltNames. */
  match_found = false;
  subj_alt_names = X509_get_ext_d2i(x509cert, NID_subject_alt_name, NULL, NULL);
  if (subj_alt_names)
  {
    subj_alt_names_count = sk_GENERAL_NAME_num(subj_alt_names);
    for (int i = 0; i < subj_alt_names_count; i++)
    {
      subj_alt_name = sk_GENERAL_NAME_value(subj_alt_names, i);
      if (subj_alt_name->type == GEN_DNS)
      {
        if ((subj_alt_name->d.ia5->length >= 0) &&
            (mutt_str_strlen((char *) subj_alt_name->d.ia5->data) ==
             (size_t) subj_alt_name->d.ia5->length) &&
            (match_found = hostname_match(hostname_ascii,
                                          (char *) (subj_alt_name->d.ia5->data))))
        {
          break;
        }
      }
    }
    GENERAL_NAMES_free(subj_alt_names);
  }

  if (!match_found)
  {
    /* Try the common name */
    x509_subject = X509_get_subject_name(x509cert);
    if (!x509_subject)
    {
      if (err && errlen)
        mutt_str_strfcpy(err, _("cannot get certificate subject"), errlen);
      goto out;
    }

    /* first get the space requirements */
    bufsize = X509_NAME_get_text_by_NID(x509_subject, NID_commonName, NULL, 0);
    if (bufsize == -1)
    {
      if (err && errlen)
        mutt_str_strfcpy(err, _("cannot get certificate common name"), errlen);
      goto out;
    }
    bufsize++; /* space for the terminal nul char */
    buf = mutt_mem_malloc((size_t) bufsize);
    if (X509_NAME_get_text_by_NID(x509_subject, NID_commonName, buf, bufsize) == -1)
    {
      if (err && errlen)
        mutt_str_strfcpy(err, _("cannot get certificate common name"), errlen);
      goto out;
    }
    /* cast is safe since bufsize is incremented above, so bufsize-1 is always
     * zero or greater.  */
    if (mutt_str_strlen(buf) == (size_t) bufsize - 1)
    {
      match_found = hostname_match(hostname_ascii, buf);
    }
  }

  if (!match_found)
  {
    if (err && errlen)
      snprintf(err, errlen, _("certificate owner does not match hostname %s"), hostname);
    goto out;
  }

  rc = 1;

out:
  FREE(&buf);
  FREE(&hostname_ascii);

  return rc;
}
Esempio n. 7
0
/**
 * mutt_draw_tree - Draw a tree of threaded emails
 * @param ctx Mailbox
 *
 * Since the graphics characters have a value >255, I have to resort to using
 * escape sequences to pass the information to print_enriched_string().  These
 * are the macros MUTT_TREE_* defined in mutt.h.
 *
 * ncurses should automatically use the default ASCII characters instead of
 * graphics chars on terminals which don't support them (see the man page for
 * curs_addch).
 */
void mutt_draw_tree(struct Context *ctx)
{
  char *pfx = NULL, *mypfx = NULL, *arrow = NULL, *myarrow = NULL, *new_tree = NULL;
  enum TreeChar corner = (C_Sort & SORT_REVERSE) ? MUTT_TREE_ULCORNER : MUTT_TREE_LLCORNER;
  enum TreeChar vtee = (C_Sort & SORT_REVERSE) ? MUTT_TREE_BTEE : MUTT_TREE_TTEE;
  int depth = 0, start_depth = 0, max_depth = 0, width = C_NarrowTree ? 1 : 2;
  struct MuttThread *nextdisp = NULL, *pseudo = NULL, *parent = NULL, *tree = ctx->tree;

  /* Do the visibility calculations and free the old thread chars.
   * From now on we can simply ignore invisible subtrees */
  calculate_visibility(ctx, &max_depth);
  pfx = mutt_mem_malloc(width * max_depth + 2);
  arrow = mutt_mem_malloc(width * max_depth + 2);
  while (tree)
  {
    if (depth)
    {
      myarrow = arrow + (depth - start_depth - (start_depth ? 0 : 1)) * width;
      if (depth && (start_depth == depth))
        myarrow[0] = nextdisp ? MUTT_TREE_LTEE : corner;
      else if (parent->message && !C_HideLimited)
        myarrow[0] = MUTT_TREE_HIDDEN;
      else if (!parent->message && !C_HideMissing)
        myarrow[0] = MUTT_TREE_MISSING;
      else
        myarrow[0] = vtee;
      if (width == 2)
      {
        myarrow[1] = pseudo ? MUTT_TREE_STAR :
                              (tree->duplicate_thread ? MUTT_TREE_EQUALS : MUTT_TREE_HLINE);
      }
      if (tree->visible)
      {
        myarrow[width] = MUTT_TREE_RARROW;
        myarrow[width + 1] = 0;
        new_tree = mutt_mem_malloc((2 + depth * width));
        if (start_depth > 1)
        {
          strncpy(new_tree, pfx, (start_depth - 1) * width);
          mutt_str_strfcpy(new_tree + (start_depth - 1) * width, arrow,
                           (1 + depth - start_depth) * width + 2);
        }
        else
          mutt_str_strfcpy(new_tree, arrow, 2 + depth * width);
        tree->message->tree = new_tree;
      }
    }
    if (tree->child && depth)
    {
      mypfx = pfx + (depth - 1) * width;
      mypfx[0] = nextdisp ? MUTT_TREE_VLINE : MUTT_TREE_SPACE;
      if (width == 2)
        mypfx[1] = MUTT_TREE_SPACE;
    }
    parent = tree;
    nextdisp = NULL;
    pseudo = NULL;
    do
    {
      if (tree->child && tree->subtree_visible)
      {
        if (tree->deep)
          depth++;
        if (tree->visible)
          start_depth = depth;
        tree = tree->child;

        /* we do this here because we need to make sure that the first child thread
         * of the old tree that we deal with is actually displayed if any are,
         * or we might set the parent variable wrong while going through it. */
        while (!tree->subtree_visible && tree->next)
          tree = tree->next;
      }
      else
      {
        while (!tree->next && tree->parent)
        {
          if (tree == pseudo)
            pseudo = NULL;
          if (tree == nextdisp)
            nextdisp = NULL;
          if (tree->visible)
            start_depth = depth;
          tree = tree->parent;
          if (tree->deep)
          {
            if (start_depth == depth)
              start_depth--;
            depth--;
          }
        }
        if (tree == pseudo)
          pseudo = NULL;
        if (tree == nextdisp)
          nextdisp = NULL;
        if (tree->visible)
          start_depth = depth;
        tree = tree->next;
        if (!tree)
          break;
      }
      if (!pseudo && tree->fake_thread)
        pseudo = tree;
      if (!nextdisp && tree->next_subtree_visible)
        nextdisp = tree;
    } while (!tree->deep);
  }

  FREE(&pfx);
  FREE(&arrow);
}