Пример #1
0
/* simple read buffering to speed things up. */
int mutt_socket_readchar (CONNECTION *conn, char *c)
{
  if (conn->bufpos >= conn->available)
  {
    if (conn->fd >= 0)
      conn->available = conn->read (conn, conn->inbuf, sizeof (conn->inbuf));
    else
    {
      dprint (1, (debugfile, "mutt_socket_readchar: attempt to read from closed connection.\n"));
      return -1;
    }
    conn->bufpos = 0;
    if (conn->available == 0)
    {
      mutt_error (_("Connection to %s closed"), conn->account.host);
      mutt_sleep (2);
    }
    if (conn->available <= 0)
    {
      mutt_socket_close (conn);
      return -1;
    }
  }
  *c = conn->inbuf[conn->bufpos];
  conn->bufpos++;
  return 1;
}
Пример #2
0
int mutt_socket_write_d (CONNECTION *conn, const char *buf, int dbg)
{
  int rc;
  int len;

  dprint (dbg, (debugfile,"> %s", buf));

  if (conn->fd < 0)
  {
    dprint (1, (debugfile, "mutt_socket_write: attempt to write to closed connection\n"));
    return -1;
  }

  len = mutt_strlen (buf);
  if ((rc = conn->write (conn, buf, len)) < 0)
  {
    dprint (1, (debugfile,
      "mutt_socket_write: error writing, closing socket\n"));
    mutt_socket_close (conn);

    return -1;
  }

  if (rc < len)
  {
    dprint (1, (debugfile,
      "mutt_socket_write: ERROR: wrote %d of %d bytes!\n", rc, len));
  }

  return rc;
}
Пример #3
0
static int ssl_socket_open (CONNECTION * conn)
{
  sslsockdata *data;
  int maxbits;

  if (raw_socket_open (conn) < 0)
    return -1;

  data = (sslsockdata *) safe_calloc (1, sizeof (sslsockdata));
  conn->sockdata = data;

  data->ctx = SSL_CTX_new (SSLv23_client_method ());

  /* disable SSL protocols as needed */
  if (!option(OPTTLSV1))
  {
    SSL_CTX_set_options(data->ctx, SSL_OP_NO_TLSv1);
  }
  /* TLSv1.1/1.2 support was added in OpenSSL 1.0.1, but some OS distros such
   * as Fedora 17 are on OpenSSL 1.0.0.
   */
#ifdef SSL_OP_NO_TLSv1_1
  if (!option(OPTTLSV1_1))
  {
    SSL_CTX_set_options(data->ctx, SSL_OP_NO_TLSv1_1);
  }
#endif
#ifdef SSL_OP_NO_TLSv1_2
  if (!option(OPTTLSV1_2))
  {
    SSL_CTX_set_options(data->ctx, SSL_OP_NO_TLSv1_2);
  }
#endif
  if (!option(OPTSSLV2))
  {
    SSL_CTX_set_options(data->ctx, SSL_OP_NO_SSLv2);
  }
  if (!option(OPTSSLV3))
  {
    SSL_CTX_set_options(data->ctx, SSL_OP_NO_SSLv3);
  }

  ssl_get_client_cert(data, conn);

  data->ssl = SSL_new (data->ctx);
  SSL_set_fd (data->ssl, conn->fd);

  if (ssl_negotiate(conn, data))
  {
    mutt_socket_close (conn);
    return -1;
  }

  data->isopen = 1;

  conn->ssf = SSL_CIPHER_get_bits (SSL_get_current_cipher (data->ssl),
    &maxbits);

  return 0;
}
Пример #4
0
int mutt_socket_write_d (CONNECTION *conn, const char *buf, int len, int dbg)
{
        int rc;
        int sent = 0;

        dprint (dbg, (debugfile,"%d> %s", conn->fd, buf));

        if (conn->fd < 0) {
                dprint (1, (debugfile, "mutt_socket_write: attempt to write to closed connection\n"));
                return -1;
        }

        if (len < 0)
                len = mutt_strlen (buf);

        while (sent < len) {
                if ((rc = conn->conn_write (conn, buf + sent, len - sent)) < 0) {
                        dprint (1, (debugfile,
                                "mutt_socket_write: error writing (%s), closing socket\n",
                                strerror(errno)));
                        mutt_socket_close (conn);

                        return -1;
                }

                if (rc < len - sent)
                        dprint (3, (debugfile,
                                "mutt_socket_write: short write (%d of %d bytes)\n", rc,
                                len - sent));

                sent += rc;
        }

        return sent;
}
Пример #5
0
/**
 * mutt_socket_readchar - simple read buffering to speed things up
 * @param[in]  conn Connection to a server
 * @param[out] c    Character that was read
 * @retval  1 Success
 * @retval -1 Error
 */
int mutt_socket_readchar(struct Connection *conn, char *c)
{
  if (conn->bufpos >= conn->available)
  {
    if (conn->fd >= 0)
      conn->available = conn->conn_read(conn, conn->inbuf, sizeof(conn->inbuf));
    else
    {
      mutt_debug(LL_DEBUG1, "attempt to read from closed connection.\n");
      return -1;
    }
    conn->bufpos = 0;
    if (conn->available == 0)
    {
      mutt_error(_("Connection to %s closed"), conn->account.host);
    }
    if (conn->available <= 0)
    {
      mutt_socket_close(conn);
      return -1;
    }
  }
  *c = conn->inbuf[conn->bufpos];
  conn->bufpos++;
  return 1;
}
Пример #6
0
/**
 * mutt_socket_write_d - Write data to a socket
 * @param conn Connection to a server
 * @param buf Buffer with data to write
 * @param len Length of data to write
 * @param dbg Debug level for logging
 * @retval >0 Number of bytes written
 * @retval -1 Error
 */
int mutt_socket_write_d(struct Connection *conn, const char *buf, int len, int dbg)
{
  int sent = 0;

  mutt_debug(dbg, "%d> %s", conn->fd, buf);

  if (conn->fd < 0)
  {
    mutt_debug(LL_DEBUG1, "attempt to write to closed connection\n");
    return -1;
  }

  while (sent < len)
  {
    const int rc = conn->conn_write(conn, buf + sent, len - sent);
    if (rc < 0)
    {
      mutt_debug(LL_DEBUG1, "error writing (%s), closing socket\n", strerror(errno));
      mutt_socket_close(conn);

      return -1;
    }

    if (rc < len - sent)
      mutt_debug(LL_DEBUG3, "short write (%d of %d bytes)\n", rc, len - sent);

    sent += rc;
  }

  return sent;
}
Пример #7
0
/* Check for new messages and fetch headers */
int pop_check_mailbox(CONTEXT *ctx, int *index_hint)
{
    int ret;
    POP_DATA *pop_data = (POP_DATA *)ctx->data;

    if ((pop_data->check_time + PopCheckTimeout) > time(NULL))
        return 0;

    pop_logout(ctx);

    mutt_socket_close(pop_data->conn);

    if (pop_open_connection(pop_data) < 0)
        return -1;

    ctx->size = pop_data->size;

    mutt_message _("Checking for new messages...");

    ret = pop_fetch_headers(ctx);
    pop_clear_cache(pop_data);

    if (ret < 0)
        return -1;

    if (ret > 0)
        return M_NEW_MAIL;

    return 0;
}
Пример #8
0
/* reconnect and verify idnexes if connection was lost */
int pop_reconnect (CONTEXT *ctx)
{
  int ret;
  POP_DATA *pop_data = (POP_DATA *)ctx->data;
  progress_t progressbar;

  if (pop_data->status == POP_CONNECTED)
    return 0;
  if (pop_data->status == POP_BYE)
    return -1;

  FOREVER
  {
    mutt_socket_close (pop_data->conn);

    ret = pop_open_connection (pop_data);
    if (ret == 0)
    {
      int i;

      mutt_progress_init (&progressbar, _("Verifying message indexes..."),
			  M_PROGRESS_SIZE, NetInc, 0);

      for (i = 0; i < ctx->msgcount; i++)
	ctx->hdrs[i]->refno = -1;

      ret = pop_fetch_data (pop_data, "UIDL\r\n", &progressbar, check_uidl, ctx);
      if (ret == -2)
      {
        mutt_error ("%s", pop_data->err_msg);
        mutt_sleep (2);
      }
    }
    if (ret == 0)
      return 0;

    pop_logout (ctx);

    if (ret < -1)
      return -1;

    if (query_quadoption (OPT_POPRECONNECT,
		_("Connection lost. Reconnect to POP server?")) != M_YES)
      return -1;
  }
}
Пример #9
0
int mutt_socket_read (CONNECTION* conn, char* buf, size_t len)
{
        int rc;

        if (conn->fd < 0) {
                dprint (1, (debugfile, "mutt_socket_read: attempt to read from closed connection\n"));
                return -1;
        }

        rc = conn->conn_read (conn, buf, len);
/* EOF */
        if (rc == 0) {
                mutt_error (_("Connection to %s closed"), conn->account.host);
                mutt_sleep (2);
        }
        if (rc <= 0)
                mutt_socket_close (conn);

        return rc;
}
Пример #10
0
/* close POP mailbox */
int pop_close_mailbox(CONTEXT *ctx)
{
    POP_DATA *pop_data = (POP_DATA *)ctx->data;

    if (!pop_data)
        return 0;

    pop_logout(ctx);

    if (pop_data->status != POP_NONE)
        mutt_socket_close(pop_data->conn);

    pop_data->status = POP_NONE;

    pop_data->clear_cache = 1;
    pop_clear_cache(pop_data);

    if (!pop_data->conn->data)
        mutt_socket_free(pop_data->conn);

    mutt_bcache_close(&pop_data->bcache);

    return 0;
}
Пример #11
0
int
mutt_smtp_send (const ADDRESS* from, const ADDRESS* to, const ADDRESS* cc,
const ADDRESS* bcc, const char *msgfile, int eightbit)
{
        CONNECTION *conn;
        ACCOUNT account;
        const char* envfrom;
        char buf[1024];
        int ret = -1;

/* it might be better to synthesize an envelope from from user and host
 * but this condition is most likely arrived at accidentally */
        if (EnvFrom)
                envfrom = EnvFrom->mailbox;
        else if (from)
                envfrom = from->mailbox;
        else {
                mutt_error (_("No from address given"));
                return -1;
        }

        if (smtp_fill_account (&account) < 0)
                return ret;

        if (!(conn = mutt_conn_find (NULL, &account)))
                return -1;

        Esmtp = eightbit;

        do {
/* send our greeting */
                if (( ret = smtp_open (conn)))
                        break;
                FREE (&AuthMechs);

/* send the sender's address */
                ret = snprintf (buf, sizeof (buf), "MAIL FROM:<%s>", envfrom);
                if (eightbit && mutt_bit_isset (Capabilities, EIGHTBITMIME)) {
                        safe_strncat (buf, sizeof (buf), " BODY=8BITMIME", 15);
                        ret += 14;
                }
                if (DsnReturn && mutt_bit_isset (Capabilities, DSN))
                        ret += snprintf (buf + ret, sizeof (buf) - ret, " RET=%s", DsnReturn);
                safe_strncat (buf, sizeof (buf), "\r\n", 3);
                if (mutt_socket_write (conn, buf) == -1) {
                        ret = smtp_err_write;
                        break;
                }
                if ((ret = smtp_get_resp (conn)))
                        break;

/* send the recipient list */
                if ((ret = smtp_rcpt_to (conn, to)) || (ret = smtp_rcpt_to (conn, cc))
                        || (ret = smtp_rcpt_to (conn, bcc)))
                        break;

/* send the message data */
                if ((ret = smtp_data (conn, msgfile)))
                        break;

                mutt_socket_write (conn, "QUIT\r\n");

                ret = 0;
        }
        while (0);

        if (conn)
                mutt_socket_close (conn);

        if (ret == smtp_err_read)
                mutt_error (_("SMTP session failed: read error"));
        else if (ret == smtp_err_write)
                mutt_error (_("SMTP session failed: write error"));
        else if (ret == smtp_err_code)
                mutt_error (_("Invalid server response"));

        return ret;
}
Пример #12
0
static int ssl_socket_open (CONNECTION * conn)
{
  sslsockdata *data;
  int maxbits;

  if (raw_socket_open (conn) < 0)
    return -1;

  data = (sslsockdata *) safe_calloc (1, sizeof (sslsockdata));
  conn->sockdata = data;

  if (! (data->ctx = SSL_CTX_new (SSLv23_client_method ())))
  {
    /* L10N: an SSL context is a data structure returned by the OpenSSL
     *       function SSL_CTX_new().  In this case it returned NULL: an
     *       error condition.
     */
    mutt_error (_("Unable to create SSL context"));
    ssl_dprint_err_stack ();
    mutt_socket_close (conn);
    return -1;
  }

  /* disable SSL protocols as needed */
  if (!option(OPTTLSV1))
  {
    SSL_CTX_set_options(data->ctx, SSL_OP_NO_TLSv1);
  }
  /* TLSv1.1/1.2 support was added in OpenSSL 1.0.1, but some OS distros such
   * as Fedora 17 are on OpenSSL 1.0.0.
   */
#ifdef SSL_OP_NO_TLSv1_1
  if (!option(OPTTLSV1_1))
  {
    SSL_CTX_set_options(data->ctx, SSL_OP_NO_TLSv1_1);
  }
#endif
#ifdef SSL_OP_NO_TLSv1_2
  if (!option(OPTTLSV1_2))
  {
    SSL_CTX_set_options(data->ctx, SSL_OP_NO_TLSv1_2);
  }
#endif
  if (!option(OPTSSLV2))
  {
    SSL_CTX_set_options(data->ctx, SSL_OP_NO_SSLv2);
  }
  if (!option(OPTSSLV3))
  {
    SSL_CTX_set_options(data->ctx, SSL_OP_NO_SSLv3);
  }

  ssl_get_client_cert(data, conn);

  if (SslCiphers) {
    SSL_CTX_set_cipher_list (data->ctx, SslCiphers);
  }

  data->ssl = SSL_new (data->ctx);
  SSL_set_fd (data->ssl, conn->fd);

  if (ssl_negotiate(conn, data))
  {
    mutt_socket_close (conn);
    return -1;
  }

  data->isopen = 1;

  conn->ssf = SSL_CIPHER_get_bits (SSL_get_current_cipher (data->ssl),
    &maxbits);

  return 0;
}
Пример #13
0
/* Fetch messages and save them in $spoolfile */
void pop_fetch_mail(void)
{
    char buffer[LONG_STRING];
    char msgbuf[SHORT_STRING];
    char *url, *p;
    int i, delanswer, last = 0, msgs, bytes, rset = 0, ret;
    CONNECTION *conn;
    CONTEXT ctx;
    MESSAGE *msg = NULL;
    ACCOUNT acct;
    POP_DATA *pop_data;

    if (!PopHost) {
        mutt_error _("POP host is not defined.");
        return;
    }

    url = p = safe_calloc(strlen(PopHost) + 7, sizeof(char));

    if (url_check_scheme(PopHost) == U_UNKNOWN) {
        strcpy(url, "pop://"); /* __STRCPY_CHECKED__ */
        p = strchr(url, '\0');
    }
    strcpy(p, PopHost);        /* __STRCPY_CHECKED__ */

    ret = pop_parse_path(url, &acct);
    safe_free(&url);

    if (ret) {
        mutt_error(_("%s is an invalid POP path"), PopHost);
        return;
    }

    conn = mutt_conn_find(NULL, &acct);

    if (!conn)
        return;

    pop_data = safe_calloc(1, sizeof(POP_DATA));
    pop_data->conn = conn;

    if (pop_open_connection(pop_data) < 0) {
        mutt_socket_free(pop_data->conn);
        safe_free(&pop_data);
        return;
    }

    conn->data = pop_data;

    mutt_message _("Checking for new messages...");

    /* find out how many messages are in the mailbox. */
    strfcpy(buffer, "STAT\r\n", sizeof(buffer));
    ret = pop_query(pop_data, buffer, sizeof(buffer));

    if (ret == -1)
        goto fail;

    if (ret == -2) {
        mutt_error("%s", pop_data->err_msg);
        goto finish;
    }

    sscanf(buffer, "+OK %d %d", &msgs, &bytes);

    /* only get unread messages */
    if ((msgs > 0)
        && option(OPTPOPLAST)) {
        strfcpy(buffer, "LAST\r\n", sizeof(buffer));
        ret = pop_query(pop_data, buffer, sizeof(buffer));

        if (ret == -1)
            goto fail;

        if (ret == 0)
            sscanf(buffer, "+OK %d", &last);
    }

    if (msgs <= last) {
        mutt_message _("No new mail in POP mailbox.");
        goto finish;
    }

    if (mx_open_mailbox(NONULL(Spoolfile), M_APPEND, &ctx) == NULL)
        goto finish;

    delanswer = query_quadoption(OPT_POPDELETE, _(
                                     "Delete messages from server?"));

    snprintf(msgbuf, sizeof(msgbuf), _(
                 "Reading new messages (%d bytes)..."), bytes);
    mutt_message("%s", msgbuf);

    for (i = last + 1; i <= msgs; i++) {
        if ((msg = mx_open_new_message(&ctx, NULL, M_ADD_FROM)) == NULL)
            ret = -3;
        else {
            snprintf(buffer, sizeof(buffer), "RETR %d\r\n", i);
            ret =
                pop_fetch_data(pop_data, buffer, NULL, fetch_message, msg->fp);

            if (ret == -3)
                rset = 1;

            if ((ret == 0)
                && (mx_commit_message(msg, &ctx) != 0)) {
                rset = 1;
                ret = -3;
            }

            mx_close_message(&msg);
        }

        if ((ret == 0)
            && (delanswer == M_YES)) {
            /* delete the message on the server */
            snprintf(buffer, sizeof(buffer), "DELE %d\r\n", i);
            ret = pop_query(pop_data, buffer, sizeof(buffer));
        }

        if (ret == -1) {
            mx_close_mailbox(&ctx, NULL);
            goto fail;
        }

        if (ret == -2) {
            mutt_error("%s", pop_data->err_msg);
            break;
        }

        if (ret == -3) {
            mutt_error _("Error while writing mailbox!");
            break;
        }

        mutt_message(_(
                         "%s [%d of %d messages read]"), msgbuf, i - last,
                     msgs - last);
    }

    mx_close_mailbox(&ctx, NULL);

    if (rset) {
        /* make sure no messages get deleted */
        strfcpy(buffer, "RSET\r\n", sizeof(buffer));

        if (pop_query(pop_data, buffer, sizeof(buffer)) == -1)
            goto fail;
    }

    finish:

    /* exit gracefully */
    strfcpy(buffer, "QUIT\r\n", sizeof(buffer));

    if (pop_query(pop_data, buffer, sizeof(buffer)) == -1)
        goto fail;
    mutt_socket_close(conn);
    safe_free(&pop_data);
    return;

    fail:
    mutt_error _("Server closed connection!");
    mutt_socket_close(conn);
    safe_free(&pop_data);
}