struct io * connectio( struct server *srv, int verify, const char *eol, int timeout, char **cause) { int fd = -1, error = 0; struct addrinfo hints; struct addrinfo *ai; const char *fn = NULL; SSL *ssl; if (srv->ai == NULL) { memset(&hints, 0, sizeof hints); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; error = getaddrinfo(srv->host, srv->port, &hints, &srv->ai); if (error != 0) { *cause = xstrdup(gai_strerror(error)); return (NULL); } } for (ai = srv->ai; ai != NULL; ai = ai->ai_next) { retry: fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (fd < 0) { fn = "socket"; continue; } if (connect(fd, ai->ai_addr, ai->ai_addrlen) < 0) { error = errno; close(fd); errno = error; if (errno == EINTR) goto retry; fd = -1; fn = "connect"; continue; } break; } if (fd < 0) { xasprintf(cause, "%s: %s", fn, strerror(errno)); return (NULL); } if (!srv->ssl) return (io_create(fd, NULL, eol)); ssl = makessl(srv, fd, verify && srv->verify, timeout, cause); if (ssl == NULL) { close(fd); return (NULL); } return (io_create(fd, ssl, eol)); }
struct io * connectproxy(struct server *srv, int verify, struct proxy *pr, const char *eol, int timeout, char **cause) { struct io *io; if (pr == NULL) return (connectio(srv, verify, eol, timeout, cause)); io = connectio(&pr->server, verify, IO_CRLF, timeout, cause); if (io == NULL) return (NULL); switch (pr->type) { case PROXY_HTTP: if (httpproxy(srv, pr, io, timeout, cause) != 0) goto error; break; case PROXY_SOCKS5: if (socks5proxy(srv, pr, io, timeout, cause) != 0) goto error; break; default: fatalx("unknown proxy type"); } /* If the original request was for SSL, initiate it now. */ if (srv->ssl) { io->ssl = makessl( srv, io->fd, verify && srv->verify, timeout, cause); if (io->ssl == NULL) goto error; } io->eol = eol; return (io); error: io_close(io); io_free(io); return (NULL); }
/* STARTTLS state. */ int imap_state_starttls(struct account *a, struct fetch_ctx *fctx) { struct fetch_imap_data *data = a->data; char *line, *cause; if (imap_getln(a, fctx, IMAP_TAGGED, &line) != 0) return (FETCH_ERROR); if (line == NULL) return (FETCH_BLOCK); if (!imap_okay(line)) return (imap_bad(a, line)); data->io->ssl = makessl(&data->server, data->io->fd, conf.verify_certs && data->server.verify, conf.timeout, &cause); if (data->io->ssl == NULL) { log_warnx("%s: STARTTLS failed: %s", a->name, cause); xfree(cause); return (FETCH_ERROR); } return (imap_pick_auth(a, fctx)); }