/* 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; }
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; }
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; }
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; }
/** * 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; }
/** * 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; }
/* 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; }
/* 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; } }
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; }
/* 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; }
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; }
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; }
/* 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); }