"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/ssl.c" between
tnftp-20151004.tar.gz and tnftp-20200705.tar.gz

About: tnftp is an enhanced ftp client (prior name "lukemftp").

ssl.c  (tnftp-20151004):ssl.c  (tnftp-20200705)
/* $NetBSD: ssl.c,v 1.3 2015/10/04 04:53:26 lukem Exp $ */ /* $NetBSD: ssl.c,v 1.4 2020/07/04 09:59:07 lukem Exp $ */
/* from NetBSD: ssl.c,v 1.5 2015/09/16 15:32:53 joerg Exp */ /* from NetBSD: ssl.c,v 1.8 2019/04/07 00:44:54 christos Exp */
/*- /*-
* Copyright (c) 1998-2004 Dag-Erling Coïdan Smørgrav * Copyright (c) 1998-2004 Dag-Erling Coïdan Smørgrav
* Copyright (c) 2008, 2010 Joerg Sonnenberger <joerg@NetBSD.org> * Copyright (c) 2008, 2010 Joerg Sonnenberger <joerg@NetBSD.org>
* Copyright (c) 2015 Thomas Klausner <wiz@NetBSD.org> * Copyright (c) 2015 Thomas Klausner <wiz@NetBSD.org>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
* are met: * are met:
skipping to change at line 42 skipping to change at line 42
* *
* $FreeBSD: common.c,v 1.53 2007/12/19 00:26:36 des Exp $ * $FreeBSD: common.c,v 1.53 2007/12/19 00:26:36 des Exp $
*/ */
#include "tnftp.h" #include "tnftp.h"
#if 0 /* tnftp */ #if 0 /* tnftp */
#include <sys/cdefs.h> #include <sys/cdefs.h>
#ifndef lint #ifndef lint
__RCSID(" NetBSD: ssl.c,v 1.5 2015/09/16 15:32:53 joerg Exp "); __RCSID(" NetBSD: ssl.c,v 1.8 2019/04/07 00:44:54 christos Exp ");
#endif #endif
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
#include <string.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/param.h> #include <sys/param.h>
#include <sys/select.h> #include <sys/select.h>
#include <sys/uio.h> #include <sys/uio.h>
#include <netinet/tcp.h> #include <netinet/tcp.h>
#include <netinet/in.h> #include <netinet/in.h>
#endif /* tnftp */ #endif /* tnftp */
skipping to change at line 97 skipping to change at line 98
/* /*
* Write a vector to a connection w/ timeout * Write a vector to a connection w/ timeout
* Note: can modify the iovec. * Note: can modify the iovec.
*/ */
static ssize_t static ssize_t
fetch_writev(struct fetch_connect *conn, struct iovec *iov, int iovcnt) fetch_writev(struct fetch_connect *conn, struct iovec *iov, int iovcnt)
{ {
struct timeval now, timeout, delta; struct timeval now, timeout, delta;
fd_set writefds; fd_set writefds;
ssize_t len, total; ssize_t len, total;
int fd = conn->sd;
int r; int r;
if (quit_time > 0) { if (quit_time > 0) {
FD_ZERO(&writefds); FD_ZERO(&writefds);
gettimeofday(&timeout, NULL); gettimeofday(&timeout, NULL);
timeout.tv_sec += quit_time; timeout.tv_sec += quit_time;
} }
total = 0; total = 0;
while (iovcnt > 0) { while (iovcnt > 0) {
while (quit_time > 0 && !FD_ISSET(conn->sd, &writefds)) { while (quit_time > 0 && !FD_ISSET(fd, &writefds)) {
FD_SET(conn->sd, &writefds); FD_SET(fd, &writefds);
gettimeofday(&now, NULL); gettimeofday(&now, NULL);
delta.tv_sec = timeout.tv_sec - now.tv_sec; delta.tv_sec = timeout.tv_sec - now.tv_sec;
delta.tv_usec = timeout.tv_usec - now.tv_usec; delta.tv_usec = timeout.tv_usec - now.tv_usec;
if (delta.tv_usec < 0) { if (delta.tv_usec < 0) {
delta.tv_usec += 1000000; delta.tv_usec += 1000000;
delta.tv_sec--; delta.tv_sec--;
} }
if (delta.tv_sec < 0) { if (delta.tv_sec < 0) {
errno = ETIMEDOUT; errno = ETIMEDOUT;
return -1; return -1;
} }
errno = 0; errno = 0;
r = select(conn->sd + 1, NULL, &writefds, NULL, &delta); r = select(fd + 1, NULL, &writefds, NULL, &delta);
if (r == -1) { if (r == -1) {
if (errno == EINTR) if (errno == EINTR)
continue; continue;
return -1; return -1;
} }
} }
errno = 0; errno = 0;
if (conn->ssl != NULL) if (conn->ssl != NULL)
len = SSL_write(conn->ssl, iov->iov_base, iov->iov_len); len = SSL_write(conn->ssl, iov->iov_base, iov->iov_len);
else else
len = writev(conn->sd, iov, iovcnt); len = writev(fd, iov, iovcnt);
if (len == 0) { if (len == 0) {
/* we consider a short write a failure */ /* we consider a short write a failure */
/* XXX perhaps we shouldn't in the SSL case */ /* XXX perhaps we shouldn't in the SSL case */
errno = EPIPE; errno = EPIPE;
return -1; return -1;
} }
if (len < 0) { if (len < 0) {
if (errno == EINTR) if (errno == EINTR || errno == EAGAIN)
continue; continue;
return -1; return -1;
} }
total += len; total += len;
while (iovcnt > 0 && len >= (ssize_t)iov->iov_len) { while (iovcnt > 0 && len >= (ssize_t)iov->iov_len) {
len -= iov->iov_len; len -= iov->iov_len;
iov++; iov++;
iovcnt--; iovcnt--;
} }
if (iovcnt > 0) { if (iovcnt > 0) {
iov->iov_len -= len; iov->iov_len -= len;
iov->iov_base = (char *)iov->iov_base + len; iov->iov_base = (char *)iov->iov_base + len;
} }
} }
return total; return total;
} }
/* static ssize_t
* Write to a connection w/ timeout fetch_write(const void *str, size_t len, struct fetch_connect *conn)
*/
static int
fetch_write(struct fetch_connect *conn, const char *str, size_t len)
{ {
struct iovec iov[1]; struct iovec iov[1];
iov[0].iov_base = (char *)__UNCONST(str); iov[0].iov_base = (char *)__UNCONST(str);
iov[0].iov_len = len; iov[0].iov_len = len;
return fetch_writev(conn, iov, 1); return fetch_writev(conn, iov, 1);
} }
/* /*
* Send a formatted line; optionally echo to terminal * Send a formatted line; optionally echo to terminal
skipping to change at line 191 skipping to change at line 190
va_start(ap, fmt); va_start(ap, fmt);
len = vasprintf(&msg, fmt, ap); len = vasprintf(&msg, fmt, ap);
va_end(ap); va_end(ap);
if (msg == NULL) { if (msg == NULL) {
errno = ENOMEM; errno = ENOMEM;
return -1; return -1;
} }
r = fetch_write(conn, msg, len); r = fetch_write(msg, len, conn);
free(msg); free(msg);
return r; return r;
} }
int int
fetch_fileno(struct fetch_connect *conn) fetch_fileno(struct fetch_connect *conn)
{ {
return conn->sd; return conn->sd;
} }
skipping to change at line 220 skipping to change at line 219
static void static void
fetch_clearerr(struct fetch_connect *conn) fetch_clearerr(struct fetch_connect *conn)
{ {
conn->iserr = 0; conn->iserr = 0;
} }
int int
fetch_flush(struct fetch_connect *conn) fetch_flush(struct fetch_connect *conn)
{ {
int v;
if (conn->issock) { if (conn->issock) {
int fd = conn->sd;
int v;
#ifdef TCP_NOPUSH #ifdef TCP_NOPUSH
v = 0; v = 0;
setsockopt(conn->sd, IPPROTO_TCP, TCP_NOPUSH, &v, sizeof(v)); setsockopt(fd, IPPROTO_TCP, TCP_NOPUSH, &v, sizeof(v));
#endif #endif
v = 1; v = 1;
setsockopt(conn->sd, IPPROTO_TCP, TCP_NODELAY, &v, sizeof(v)); setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &v, sizeof(v));
} }
return 0; return 0;
} }
/*ARGSUSED*/ /*ARGSUSED*/
struct fetch_connect * struct fetch_connect *
fetch_open(const char *fname, const char *fmode) fetch_open(const char *fname, const char *fmode)
{ {
struct fetch_connect *conn; struct fetch_connect *conn;
int fd; int fd;
skipping to change at line 281 skipping to change at line 281
#endif #endif
#ifdef TCP_NOPUSH #ifdef TCP_NOPUSH
setsockopt(sd, IPPROTO_TCP, TCP_NOPUSH, &opt, sizeof(opt)); setsockopt(sd, IPPROTO_TCP, TCP_NOPUSH, &opt, sizeof(opt));
#endif #endif
return conn; return conn;
} }
int int
fetch_close(struct fetch_connect *conn) fetch_close(struct fetch_connect *conn)
{ {
int rv = 0; if (conn == NULL)
return 0;
if (conn != NULL) { fetch_flush(conn);
fetch_flush(conn); SSL_free(conn->ssl);
SSL_free(conn->ssl); close(conn->sd);
rv = close(conn->sd); free(conn->cache.buf);
if (rv < 0) { free(conn->buf);
errno = rv; free(conn);
rv = EOF; return 0;
}
free(conn->cache.buf);
free(conn->buf);
free(conn);
}
return rv;
} }
#define FETCH_WRITE_WAIT -3
#define FETCH_READ_WAIT -2 #define FETCH_READ_WAIT -2
#define FETCH_READ_ERROR -1 #define FETCH_READ_ERROR -1
static ssize_t static ssize_t
fetch_ssl_read(SSL *ssl, void *buf, size_t len) fetch_ssl_read(SSL *ssl, void *buf, size_t len)
{ {
ssize_t rlen; ssize_t rlen;
int ssl_err;
rlen = SSL_read(ssl, buf, len); rlen = SSL_read(ssl, buf, len);
if (rlen < 0) { if (rlen >= 0)
ssl_err = SSL_get_error(ssl, rlen); return rlen;
if (ssl_err == SSL_ERROR_WANT_READ ||
ssl_err == SSL_ERROR_WANT_WRITE) { switch (SSL_get_error(ssl, rlen)) {
return FETCH_READ_WAIT; case SSL_ERROR_WANT_READ:
} return FETCH_READ_WAIT;
case SSL_ERROR_WANT_WRITE:
return FETCH_WRITE_WAIT;
default:
ERR_print_errors_fp(ttyout); ERR_print_errors_fp(ttyout);
return FETCH_READ_ERROR; return FETCH_READ_ERROR;
} }
return rlen;
} }
static ssize_t static ssize_t
fetch_nonssl_read(int sd, void *buf, size_t len) fetch_nonssl_read(int sd, void *buf, size_t len)
{ {
ssize_t rlen; ssize_t rlen;
rlen = read(sd, buf, len); rlen = read(sd, buf, len);
if (rlen < 0) { if (rlen == -1) {
if (errno == EAGAIN || errno == EINTR) if (errno == EAGAIN || errno == EINTR)
return FETCH_READ_WAIT; return FETCH_READ_WAIT;
return FETCH_READ_ERROR; return FETCH_READ_ERROR;
} }
return rlen; return rlen;
} }
/* /*
* Cache some data that was read from a socket but cannot be immediately * Cache some data that was read from a socket but cannot be immediately
* returned because of an interrupted system call. * returned because of an interrupted system call.
skipping to change at line 357 skipping to change at line 353
conn->cache.buf = tmp; conn->cache.buf = tmp;
conn->cache.size = nbytes; conn->cache.size = nbytes;
} }
memcpy(conn->cache.buf, src, nbytes); memcpy(conn->cache.buf, src, nbytes);
conn->cache.len = nbytes; conn->cache.len = nbytes;
conn->cache.pos = 0; conn->cache.pos = 0;
return 0; return 0;
} }
ssize_t static int
fetch_wait(struct fetch_connect *conn, ssize_t rlen, struct timeval *timeout)
{
struct timeval now, delta;
int fd = conn->sd;
fd_set fds;
FD_ZERO(&fds);
while (!FD_ISSET(fd, &fds)) {
FD_SET(fd, &fds);
if (quit_time > 0) {
gettimeofday(&now, NULL);
if (!timercmp(timeout, &now, >)) {
conn->iserr = ETIMEDOUT;
return -1;
}
timersub(timeout, &now, &delta);
}
errno = 0;
if (select(fd + 1,
rlen == FETCH_READ_WAIT ? &fds : NULL,
rlen == FETCH_WRITE_WAIT ? &fds : NULL,
NULL, quit_time > 0 ? &delta : NULL) < 0) {
if (errno == EINTR)
continue;
conn->iserr = errno;
return -1;
}
}
return 0;
}
size_t
fetch_read(void *ptr, size_t size, size_t nmemb, struct fetch_connect *conn) fetch_read(void *ptr, size_t size, size_t nmemb, struct fetch_connect *conn)
{ {
struct timeval now, timeout, delta;
fd_set readfds;
ssize_t rlen, total; ssize_t rlen, total;
size_t len; size_t len;
char *start, *buf; char *start, *buf;
struct timeval timeout;
if (quit_time > 0) { if (quit_time > 0) {
gettimeofday(&timeout, NULL); gettimeofday(&timeout, NULL);
timeout.tv_sec += quit_time; timeout.tv_sec += quit_time;
} }
total = 0; total = 0;
start = buf = ptr; start = buf = ptr;
len = size * nmemb; len = size * nmemb;
skipping to change at line 416 skipping to change at line 443
* SSL_read() one additional time after we've read * SSL_read() one additional time after we've read
* everything we received. * everything we received.
* *
* In the non-SSL case, it may improve performance (very * In the non-SSL case, it may improve performance (very
* slightly) when reading small amounts of data. * slightly) when reading small amounts of data.
*/ */
if (conn->ssl != NULL) if (conn->ssl != NULL)
rlen = fetch_ssl_read(conn->ssl, buf, len); rlen = fetch_ssl_read(conn->ssl, buf, len);
else else
rlen = fetch_nonssl_read(conn->sd, buf, len); rlen = fetch_nonssl_read(conn->sd, buf, len);
if (rlen == 0) { switch (rlen) {
case 0:
conn->iseof = 1;
return total;
case FETCH_READ_ERROR:
conn->iserr = errno;
if (errno == EINTR)
fetch_cache_data(conn, start, total);
return 0;
case FETCH_READ_WAIT:
case FETCH_WRITE_WAIT:
if (fetch_wait(conn, rlen, &timeout) == -1)
return 0;
break; break;
} else if (rlen > 0) { default:
len -= rlen; len -= rlen;
buf += rlen; buf += rlen;
total += rlen; total += rlen;
continue; break;
} else if (rlen == FETCH_READ_ERROR) {
if (errno == EINTR)
fetch_cache_data(conn, start, total);
return -1;
}
FD_ZERO(&readfds);
while (!FD_ISSET(conn->sd, &readfds)) {
FD_SET(conn->sd, &readfds);
if (quit_time > 0) {
gettimeofday(&now, NULL);
if (!timercmp(&timeout, &now, >)) {
errno = ETIMEDOUT;
return -1;
}
timersub(&timeout, &now, &delta);
}
errno = 0;
if (select(conn->sd + 1, &readfds, NULL, NULL,
quit_time > 0 ? &delta : NULL) < 0) {
if (errno == EINTR)
continue;
return -1;
}
} }
} }
return total; return total;
} }
#define MIN_BUF_SIZE 1024 #define MIN_BUF_SIZE 1024
/* /*
* Read a line of text from a connection w/ timeout * Read a line of text from a connection w/ timeout
*/ */
char * char *
fetch_getln(char *str, int size, struct fetch_connect *conn) fetch_getln(char *str, int size, struct fetch_connect *conn)
{ {
size_t tmpsize; size_t tmpsize;
ssize_t len; size_t len;
char c; char c;
if (conn->buf == NULL) { if (conn->buf == NULL) {
if ((conn->buf = malloc(MIN_BUF_SIZE)) == NULL) { if ((conn->buf = malloc(MIN_BUF_SIZE)) == NULL) {
errno = ENOMEM; errno = ENOMEM;
conn->iserr = 1; conn->iserr = 1;
return NULL; return NULL;
} }
conn->bufsize = MIN_BUF_SIZE; conn->bufsize = MIN_BUF_SIZE;
} }
skipping to change at line 483 skipping to change at line 499
return NULL; return NULL;
if (conn->buflen - conn->bufpos > 0) if (conn->buflen - conn->bufpos > 0)
goto done; goto done;
conn->buf[0] = '\0'; conn->buf[0] = '\0';
conn->bufpos = 0; conn->bufpos = 0;
conn->buflen = 0; conn->buflen = 0;
do { do {
len = fetch_read(&c, sizeof(c), 1, conn); len = fetch_read(&c, sizeof(c), 1, conn);
if (len == -1) {
conn->iserr = 1;
return NULL;
}
if (len == 0) { if (len == 0) {
conn->iseof = 1; if (conn->iserr)
break; return NULL;
if (conn->iseof)
break;
abort();
} }
conn->buf[conn->buflen++] = c; conn->buf[conn->buflen++] = c;
if (conn->buflen == conn->bufsize) { if (conn->buflen == conn->bufsize) {
char *tmp = conn->buf; char *tmp = conn->buf;
tmpsize = conn->bufsize * 2 + 1; tmpsize = conn->bufsize * 2 + 1;
if ((tmp = realloc(tmp, tmpsize)) == NULL) { if ((tmp = realloc(tmp, tmpsize)) == NULL) {
errno = ENOMEM; errno = ENOMEM;
conn->iserr = 1; conn->iserr = 1;
return NULL; return NULL;
} }
skipping to change at line 541 skipping to change at line 556
} }
fetch_clearerr(conn); fetch_clearerr(conn);
return rv; return rv;
} }
len = strlen(buf); len = strlen(buf);
if (buf[len - 1] == '\n') { /* clear any trailing newline */ if (buf[len - 1] == '\n') { /* clear any trailing newline */
buf[--len] = '\0'; buf[--len] = '\0';
} else if (len == buflen - 1) { /* line too long */ } else if (len == buflen - 1) { /* line too long */
while (1) { while (1) {
char c; char c;
ssize_t rlen = fetch_read(&c, sizeof(c), 1, conn); size_t rlen = fetch_read(&c, sizeof(c), 1, conn);
if (rlen <= 0 || c == '\n') if (rlen == 0 || c == '\n')
break; break;
} }
if (errormsg) if (errormsg)
*errormsg = "Input line is too long"; *errormsg = "Input line is too long";
fetch_clearerr(conn); fetch_clearerr(conn);
return -3; return -3;
} }
if (errormsg) if (errormsg)
*errormsg = NULL; *errormsg = NULL;
return len; return len;
 End of changes. 31 change blocks. 
79 lines changed or deleted 94 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)