|
|
|
@ -186,3 +186,84 @@ int tls_close(struct tlsport *p)
|
|
|
|
|
|
|
|
|
|
return e;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ssize_t tls_io(struct tlsport *p, void *buf, size_t bf_size, tls_io_dir_t dr)
|
|
|
|
|
{
|
|
|
|
|
int sel_read, sel_write;
|
|
|
|
|
int r, w = 0;
|
|
|
|
|
fd_set readfd, writefd;
|
|
|
|
|
|
|
|
|
|
if(!p || !buf) {
|
|
|
|
|
errno = EINVAL;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(!bf_size) {
|
|
|
|
|
errno = EINVAL;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ssllib_io:
|
|
|
|
|
sel_read = sel_write = 0;
|
|
|
|
|
do {
|
|
|
|
|
switch(dr) {
|
|
|
|
|
case TLSIO_READ:
|
|
|
|
|
r = SSL_read(p->ssl, buf, bf_size);
|
|
|
|
|
if(r > 0) return r;
|
|
|
|
|
break;
|
|
|
|
|
case TLSIO_WRITE:
|
|
|
|
|
r = SSL_write(p->ssl, (char *)buf + sizeof(char)*w, bf_size - w);
|
|
|
|
|
if(r == (bf_size - w)) return bf_size;
|
|
|
|
|
else if(r > 0) w += r;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
errno = EINVAL;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch(SSL_get_error(p->ssl, r)) {
|
|
|
|
|
case SSL_ERROR_NONE:
|
|
|
|
|
break;
|
|
|
|
|
case SSL_ERROR_WANT_READ:
|
|
|
|
|
sel_read = 1; /* is required to wait during read */ break;
|
|
|
|
|
case SSL_ERROR_WANT_WRITE:
|
|
|
|
|
sel_write = 1; /* is required to wait during write */ break;
|
|
|
|
|
case SSL_ERROR_WANT_CONNECT:
|
|
|
|
|
case SSL_ERROR_WANT_ACCEPT:
|
|
|
|
|
break;
|
|
|
|
|
case SSL_ERROR_SYSCALL:
|
|
|
|
|
if(errno == EAGAIN || errno == EINTR) break;
|
|
|
|
|
case SSL_ERROR_SSL:
|
|
|
|
|
case SSL_ERROR_ZERO_RETURN: /* expected close */
|
|
|
|
|
default:
|
|
|
|
|
return -1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
} while(SSL_pending(p->ssl) && !sel_read);
|
|
|
|
|
|
|
|
|
|
/* wait to read */
|
|
|
|
|
if(r != SSL_ERROR_NONE && sel_read) {
|
|
|
|
|
FD_ZERO(&readfd);
|
|
|
|
|
FD_SET(p->fd, &readfd);
|
|
|
|
|
|
|
|
|
|
ioread_select:
|
|
|
|
|
r = select(p->fd + 1, &readfd, NULL, NULL, NULL);
|
|
|
|
|
if(r <= 0) {
|
|
|
|
|
if(errno == EAGAIN || errno == EINTR) goto ioread_select;
|
|
|
|
|
else return -1;
|
|
|
|
|
} else if(FD_ISSET(p->fd, &readfd)) goto ssllib_io;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* wait to write */
|
|
|
|
|
if(r != SSL_ERROR_NONE && sel_write) {
|
|
|
|
|
FD_ZERO(&readfd);
|
|
|
|
|
FD_ZERO(&writefd);
|
|
|
|
|
FD_SET(p->fd, &readfd);
|
|
|
|
|
FD_SET(p->fd, &writefd);
|
|
|
|
|
|
|
|
|
|
r = select(p->fd + 1, &readfd, &writefd, NULL, NULL);
|
|
|
|
|
if(r && FD_ISSET(p->fd, &writefd)) goto ssllib_io;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|