check in v3.8.2 source
This commit is contained in:
190
crypto/bio/b_dump.c
Normal file
190
crypto/bio/b_dump.c
Normal file
@@ -0,0 +1,190 @@
|
||||
/* $OpenBSD: b_dump.c,v 1.26 2023/07/29 02:32:00 tb Exp $ */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
/*
|
||||
* Stolen from tjh's ssl/ssl_trc.c stuff.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/bio.h>
|
||||
|
||||
#define TRUNCATE
|
||||
#define DUMP_WIDTH 16
|
||||
#define DUMP_WIDTH_LESS_INDENT(i) (DUMP_WIDTH - ((i - (i > 6 ? 6 : i) + 3) / 4))
|
||||
|
||||
int
|
||||
BIO_dump_cb(int (*cb)(const void *data, size_t len, void *u),
|
||||
void *u, const char *s, int len)
|
||||
{
|
||||
return BIO_dump_indent_cb(cb, u, s, len, 0);
|
||||
}
|
||||
|
||||
int
|
||||
BIO_dump_indent_cb(int (*cb)(const void *data, size_t len, void *u),
|
||||
void *u, const char *s, int len, int indent)
|
||||
{
|
||||
char buf[288 + 1], tmp[20], str[128 + 1];
|
||||
int i, j, rows, trc, written;
|
||||
unsigned char ch;
|
||||
int dump_width;
|
||||
int ret = 0;
|
||||
|
||||
trc = 0;
|
||||
|
||||
#ifdef TRUNCATE
|
||||
for (; (len > 0) && ((s[len - 1] == ' ') || (s[len - 1] == '\0')); len--)
|
||||
trc++;
|
||||
#endif
|
||||
|
||||
if (indent < 0)
|
||||
indent = 0;
|
||||
if (indent > 64)
|
||||
indent = 64;
|
||||
memset(str, ' ', indent);
|
||||
str[indent] = '\0';
|
||||
|
||||
if ((dump_width = DUMP_WIDTH_LESS_INDENT(indent)) <= 0)
|
||||
return -1;
|
||||
rows = (len / dump_width);
|
||||
if ((rows * dump_width) < len)
|
||||
rows++;
|
||||
for (i = 0; i < rows; i++) {
|
||||
strlcpy(buf, str, sizeof buf);
|
||||
snprintf(tmp, sizeof tmp, "%04x - ", i*dump_width);
|
||||
strlcat(buf, tmp, sizeof buf);
|
||||
for (j = 0; j < dump_width; j++) {
|
||||
if (((i*dump_width) + j) >= len) {
|
||||
strlcat(buf, " ", sizeof buf);
|
||||
} else {
|
||||
ch = ((unsigned char)*(s + i*dump_width + j)) & 0xff;
|
||||
snprintf(tmp, sizeof tmp, "%02x%c", ch,
|
||||
j == 7 ? '-' : ' ');
|
||||
strlcat(buf, tmp, sizeof buf);
|
||||
}
|
||||
}
|
||||
strlcat(buf, " ", sizeof buf);
|
||||
for (j = 0; j < dump_width; j++) {
|
||||
if (((i*dump_width) + j) >= len)
|
||||
break;
|
||||
ch = ((unsigned char)*(s + i * dump_width + j)) & 0xff;
|
||||
snprintf(tmp, sizeof tmp, "%c",
|
||||
((ch >= ' ') && (ch <= '~')) ? ch : '.');
|
||||
strlcat(buf, tmp, sizeof buf);
|
||||
}
|
||||
strlcat(buf, "\n", sizeof buf);
|
||||
/* if this is the last call then update the ddt_dump thing so
|
||||
* that we will move the selection point in the debug window
|
||||
*/
|
||||
if ((written = cb((void *)buf, strlen(buf), u)) < 0)
|
||||
return -1;
|
||||
ret += written;
|
||||
|
||||
}
|
||||
#ifdef TRUNCATE
|
||||
if (trc > 0) {
|
||||
snprintf(buf, sizeof buf, "%s%04x - <SPACES/NULS>\n",
|
||||
str, len + trc);
|
||||
if ((written = cb((void *)buf, strlen(buf), u)) < 0)
|
||||
return -1;
|
||||
ret += written;
|
||||
}
|
||||
#endif
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
write_fp(const void *data, size_t len, void *fp)
|
||||
{
|
||||
return fwrite(data, 1, len, fp);
|
||||
}
|
||||
|
||||
int
|
||||
BIO_dump_fp(FILE *fp, const char *s, int len)
|
||||
{
|
||||
return BIO_dump_cb(write_fp, fp, s, len);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_dump_fp);
|
||||
|
||||
int
|
||||
BIO_dump_indent_fp(FILE *fp, const char *s, int len, int indent)
|
||||
{
|
||||
return BIO_dump_indent_cb(write_fp, fp, s, len, indent);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_dump_indent_fp);
|
||||
|
||||
static int
|
||||
write_bio(const void *data, size_t len, void *bp)
|
||||
{
|
||||
return BIO_write((BIO *)bp, (const char *)data, len);
|
||||
}
|
||||
|
||||
int
|
||||
BIO_dump(BIO *bp, const char *s, int len)
|
||||
{
|
||||
return BIO_dump_cb(write_bio, bp, s, len);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_dump);
|
||||
|
||||
int
|
||||
BIO_dump_indent(BIO *bp, const char *s, int len, int indent)
|
||||
{
|
||||
return BIO_dump_indent_cb(write_bio, bp, s, len, indent);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_dump_indent);
|
93
crypto/bio/b_posix.c
Normal file
93
crypto/bio/b_posix.c
Normal file
@@ -0,0 +1,93 @@
|
||||
/* $OpenBSD: b_posix.c,v 1.3 2023/07/05 21:23:37 beck Exp $ */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
/*
|
||||
* Functions that need to be overridden by non-POSIX operating systems.
|
||||
*/
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <openssl/bio.h>
|
||||
|
||||
int
|
||||
BIO_sock_init(void)
|
||||
{
|
||||
if (!OPENSSL_init_crypto(0, NULL)) /* XXX do we need this? */
|
||||
return (0);
|
||||
return (1);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_sock_init);
|
||||
|
||||
void
|
||||
BIO_sock_cleanup(void)
|
||||
{
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_sock_cleanup);
|
||||
|
||||
int
|
||||
BIO_socket_nbio(int s, int mode)
|
||||
{
|
||||
int flags = fcntl(s, F_GETFD);
|
||||
if (mode && !(flags & O_NONBLOCK))
|
||||
return (fcntl(s, F_SETFL, flags | O_NONBLOCK) != -1);
|
||||
else if (!mode && (flags & O_NONBLOCK))
|
||||
return (fcntl(s, F_SETFL, flags & ~O_NONBLOCK) != -1);
|
||||
return (1);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_socket_nbio);
|
111
crypto/bio/b_print.c
Normal file
111
crypto/bio/b_print.c
Normal file
@@ -0,0 +1,111 @@
|
||||
/* $OpenBSD: b_print.c,v 1.27 2023/07/05 21:23:37 beck Exp $ */
|
||||
|
||||
/* Theo de Raadt places this file in the public domain. */
|
||||
|
||||
#include <openssl/bio.h>
|
||||
|
||||
int
|
||||
BIO_printf(BIO *bio, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
int ret;
|
||||
|
||||
va_start(args, format);
|
||||
ret = BIO_vprintf(bio, format, args);
|
||||
va_end(args);
|
||||
return (ret);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_printf);
|
||||
|
||||
#ifdef HAVE_FUNOPEN
|
||||
static int
|
||||
_BIO_write(void *cookie, const char *buf, int nbytes)
|
||||
{
|
||||
return BIO_write(cookie, buf, nbytes);
|
||||
}
|
||||
|
||||
int
|
||||
BIO_vprintf(BIO *bio, const char *format, va_list args)
|
||||
{
|
||||
int ret;
|
||||
FILE *fp;
|
||||
|
||||
fp = funopen(bio, NULL, &_BIO_write, NULL, NULL);
|
||||
if (fp == NULL) {
|
||||
ret = -1;
|
||||
goto fail;
|
||||
}
|
||||
ret = vfprintf(fp, format, args);
|
||||
fclose(fp);
|
||||
fail:
|
||||
return (ret);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_vprintf);
|
||||
|
||||
#else /* !HAVE_FUNOPEN */
|
||||
|
||||
int
|
||||
BIO_vprintf(BIO *bio, const char *format, va_list args)
|
||||
{
|
||||
int ret;
|
||||
char *buf = NULL;
|
||||
|
||||
ret = vasprintf(&buf, format, args);
|
||||
if (ret == -1)
|
||||
return (ret);
|
||||
BIO_write(bio, buf, ret);
|
||||
free(buf);
|
||||
return (ret);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_vprintf);
|
||||
|
||||
#endif /* HAVE_FUNOPEN */
|
||||
|
||||
/*
|
||||
* BIO_snprintf and BIO_vsnprintf return -1 for overflow,
|
||||
* due to the history of this API. Justification:
|
||||
*
|
||||
* Traditional snprintf surfaced in 4.4BSD, and returned
|
||||
* "number of bytes wanted". Solaris and Windows opted to
|
||||
* return -1. A draft standard was written which returned -1.
|
||||
* Due to the large volume of code already using the first
|
||||
* semantics, the draft was repaired before standardization to
|
||||
* specify "number of bytes wanted" plus "-1 for character conversion
|
||||
* style errors". Solaris adapted to this rule, but Windows stuck
|
||||
* with -1.
|
||||
*
|
||||
* Original OpenSSL comment which is full of lies:
|
||||
*
|
||||
* "In case of truncation, return -1 like traditional snprintf.
|
||||
* (Current drafts for ISO/IEC 9899 say snprintf should return
|
||||
* the number of characters that would have been written,
|
||||
* had the buffer been large enough.)"
|
||||
*/
|
||||
int
|
||||
BIO_snprintf(char *buf, size_t n, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
int ret;
|
||||
|
||||
va_start(args, format);
|
||||
ret = vsnprintf(buf, n, format, args);
|
||||
va_end(args);
|
||||
|
||||
if (ret >= n || ret == -1)
|
||||
return (-1);
|
||||
return (ret);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_snprintf);
|
||||
|
||||
int
|
||||
BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = vsnprintf(buf, n, format, args);
|
||||
|
||||
if (ret >= n || ret == -1)
|
||||
return (-1);
|
||||
return (ret);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_vsnprintf);
|
261
crypto/bio/b_sock.c
Normal file
261
crypto/bio/b_sock.c
Normal file
@@ -0,0 +1,261 @@
|
||||
/* $OpenBSD: b_sock.c,v 1.71 2023/07/05 21:23:37 beck Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2017 Bob Beck <beck@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/buffer.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
int
|
||||
BIO_get_host_ip(const char *str, unsigned char *ip)
|
||||
{
|
||||
struct addrinfo *res = NULL;
|
||||
struct addrinfo hints = {
|
||||
.ai_family = AF_INET,
|
||||
.ai_socktype = SOCK_STREAM,
|
||||
.ai_flags = AI_PASSIVE,
|
||||
};
|
||||
uint32_t *iap = (in_addr_t *)ip;
|
||||
int error;
|
||||
|
||||
if (str == NULL) {
|
||||
BIOerror(BIO_R_BAD_HOSTNAME_LOOKUP);
|
||||
ERR_asprintf_error_data("NULL host provided");
|
||||
return (0);
|
||||
}
|
||||
|
||||
if ((error = getaddrinfo(str, NULL, &hints, &res)) != 0) {
|
||||
BIOerror(BIO_R_BAD_HOSTNAME_LOOKUP);
|
||||
ERR_asprintf_error_data("getaddrinfo: host='%s' : %s'", str,
|
||||
gai_strerror(error));
|
||||
return (0);
|
||||
}
|
||||
*iap = (uint32_t)(((struct sockaddr_in *)(res->ai_addr))->sin_addr.s_addr);
|
||||
freeaddrinfo(res);
|
||||
return (1);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_get_host_ip);
|
||||
|
||||
int
|
||||
BIO_get_port(const char *str, unsigned short *port_ptr)
|
||||
{
|
||||
struct addrinfo *res = NULL;
|
||||
struct addrinfo hints = {
|
||||
.ai_family = AF_UNSPEC,
|
||||
.ai_socktype = SOCK_STREAM,
|
||||
.ai_flags = AI_PASSIVE,
|
||||
};
|
||||
int error;
|
||||
|
||||
if (str == NULL) {
|
||||
BIOerror(BIO_R_NO_PORT_SPECIFIED);
|
||||
return (0);
|
||||
}
|
||||
|
||||
if ((error = getaddrinfo(NULL, str, &hints, &res)) != 0) {
|
||||
BIOerror(BIO_R_INVALID_ARGUMENT);
|
||||
ERR_asprintf_error_data("getaddrinfo: service='%s' : %s'", str,
|
||||
gai_strerror(error));
|
||||
return (0);
|
||||
}
|
||||
*port_ptr = ntohs(((struct sockaddr_in *)(res->ai_addr))->sin_port);
|
||||
freeaddrinfo(res);
|
||||
return (1);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_get_port);
|
||||
|
||||
int
|
||||
BIO_sock_error(int sock)
|
||||
{
|
||||
socklen_t len;
|
||||
int err;
|
||||
|
||||
len = sizeof(err);
|
||||
if (getsockopt(sock, SOL_SOCKET, SO_ERROR, &err, &len) != 0)
|
||||
return (1);
|
||||
return (err);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_sock_error);
|
||||
|
||||
struct hostent *
|
||||
BIO_gethostbyname(const char *name)
|
||||
{
|
||||
return gethostbyname(name);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_gethostbyname);
|
||||
|
||||
int
|
||||
BIO_socket_ioctl(int fd, long type, void *arg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ioctl(fd, type, arg);
|
||||
if (ret < 0)
|
||||
SYSerror(errno);
|
||||
return (ret);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_socket_ioctl);
|
||||
|
||||
int
|
||||
BIO_get_accept_socket(char *host, int bind_mode)
|
||||
{
|
||||
struct addrinfo hints = {
|
||||
.ai_family = AF_INET,
|
||||
.ai_socktype = SOCK_STREAM,
|
||||
.ai_flags = AI_PASSIVE,
|
||||
};
|
||||
struct addrinfo *res = NULL;
|
||||
char *h, *p, *str = NULL;
|
||||
int error, ret = 0, s = -1;
|
||||
|
||||
if (host == NULL) {
|
||||
BIOerror(BIO_R_NO_PORT_SPECIFIED);
|
||||
return (-1);
|
||||
}
|
||||
if ((str = strdup(host)) == NULL) {
|
||||
BIOerror(ERR_R_MALLOC_FAILURE);
|
||||
return (-1);
|
||||
}
|
||||
p = NULL;
|
||||
h = str;
|
||||
if ((p = strrchr(str, ':')) == NULL) {
|
||||
/* A string without a colon is treated as a port. */
|
||||
p = str;
|
||||
h = NULL;
|
||||
} else {
|
||||
*p++ = '\0';
|
||||
if (*p == '\0') {
|
||||
BIOerror(BIO_R_NO_PORT_SPECIFIED);
|
||||
goto err;
|
||||
}
|
||||
if (*h == '\0' || strcmp(h, "*") == 0)
|
||||
h = NULL;
|
||||
}
|
||||
|
||||
if ((error = getaddrinfo(h, p, &hints, &res)) != 0) {
|
||||
BIOerror(BIO_R_BAD_HOSTNAME_LOOKUP);
|
||||
ERR_asprintf_error_data("getaddrinfo: '%s:%s': %s'", h, p,
|
||||
gai_strerror(error));
|
||||
goto err;
|
||||
}
|
||||
if (h == NULL) {
|
||||
struct sockaddr_in *sin = (struct sockaddr_in *)res->ai_addr;
|
||||
sin->sin_addr.s_addr = INADDR_ANY;
|
||||
}
|
||||
|
||||
s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (s == -1) {
|
||||
SYSerror(errno);
|
||||
ERR_asprintf_error_data("host='%s'", host);
|
||||
BIOerror(BIO_R_UNABLE_TO_CREATE_SOCKET);
|
||||
goto err;
|
||||
}
|
||||
if (bind_mode == BIO_BIND_REUSEADDR) {
|
||||
int i = 1;
|
||||
|
||||
ret = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));
|
||||
bind_mode = BIO_BIND_NORMAL;
|
||||
}
|
||||
if (bind(s, res->ai_addr, res->ai_addrlen) == -1) {
|
||||
SYSerror(errno);
|
||||
ERR_asprintf_error_data("host='%s'", host);
|
||||
BIOerror(BIO_R_UNABLE_TO_BIND_SOCKET);
|
||||
goto err;
|
||||
}
|
||||
if (listen(s, SOMAXCONN) == -1) {
|
||||
SYSerror(errno);
|
||||
ERR_asprintf_error_data("host='%s'", host);
|
||||
BIOerror(BIO_R_UNABLE_TO_LISTEN_SOCKET);
|
||||
goto err;
|
||||
}
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
free(str);
|
||||
if (res != NULL)
|
||||
freeaddrinfo(res);
|
||||
if ((ret == 0) && (s != -1)) {
|
||||
close(s);
|
||||
s = -1;
|
||||
}
|
||||
return (s);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_get_accept_socket);
|
||||
|
||||
int
|
||||
BIO_accept(int sock, char **addr)
|
||||
{
|
||||
char h[NI_MAXHOST], s[NI_MAXSERV];
|
||||
struct sockaddr_in sin;
|
||||
socklen_t sin_len = sizeof(sin);
|
||||
int ret = -1;
|
||||
|
||||
if (addr == NULL) {
|
||||
BIOerror(BIO_R_NULL_PARAMETER);
|
||||
goto end;
|
||||
}
|
||||
ret = accept(sock, (struct sockaddr *)&sin, &sin_len);
|
||||
if (ret == -1) {
|
||||
if (BIO_sock_should_retry(ret))
|
||||
return -2;
|
||||
SYSerror(errno);
|
||||
BIOerror(BIO_R_ACCEPT_ERROR);
|
||||
goto end;
|
||||
}
|
||||
/* XXX Crazy API. Can't be helped */
|
||||
if (*addr != NULL) {
|
||||
free(*addr);
|
||||
*addr = NULL;
|
||||
}
|
||||
|
||||
if (sin.sin_family != AF_INET)
|
||||
goto end;
|
||||
|
||||
if (getnameinfo((struct sockaddr *)&sin, sin_len, h, sizeof(h),
|
||||
s, sizeof(s), NI_NUMERICHOST|NI_NUMERICSERV) != 0)
|
||||
goto end;
|
||||
|
||||
if ((asprintf(addr, "%s:%s", h, s)) == -1) {
|
||||
BIOerror(ERR_R_MALLOC_FAILURE);
|
||||
*addr = NULL;
|
||||
goto end;
|
||||
}
|
||||
end:
|
||||
return (ret);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_accept);
|
||||
|
||||
int
|
||||
BIO_set_tcp_ndelay(int s, int on)
|
||||
{
|
||||
return (setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) == 0);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_set_tcp_ndelay);
|
54
crypto/bio/b_win.c
Normal file
54
crypto/bio/b_win.c
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Public domain
|
||||
*
|
||||
* Dongsheng Song <dongsheng.song@gmail.com>
|
||||
* Brent Cook <bcook@openbsd.org>
|
||||
*/
|
||||
|
||||
#include <ws2tcpip.h>
|
||||
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
int
|
||||
BIO_sock_init(void)
|
||||
{
|
||||
/*
|
||||
* WSAStartup loads the winsock .dll and initializes the networking
|
||||
* stack on Windows, or simply increases the reference count.
|
||||
*/
|
||||
static struct WSAData wsa_state = {0};
|
||||
WORD version_requested = MAKEWORD(2, 2);
|
||||
static int wsa_init_done = 0;
|
||||
if (!wsa_init_done) {
|
||||
if (WSAStartup(version_requested, &wsa_state) != 0) {
|
||||
int err = WSAGetLastError();
|
||||
SYSerror(err);
|
||||
BIOerror(BIO_R_WSASTARTUP);
|
||||
return (-1);
|
||||
}
|
||||
wsa_init_done = 1;
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
void
|
||||
BIO_sock_cleanup(void)
|
||||
{
|
||||
/*
|
||||
* We could call WSACleanup here, but it is easy to get it wrong. Since
|
||||
* this API provides no way to even tell if it failed, there is no safe
|
||||
* way to expose that functionality here.
|
||||
*
|
||||
* The cost of leaving the networking DLLs loaded may have been large
|
||||
* during the Windows 3.1/win32s era, but it is small in modern
|
||||
* contexts, so don't bother.
|
||||
*/
|
||||
}
|
||||
|
||||
int
|
||||
BIO_socket_nbio(int s, int mode)
|
||||
{
|
||||
u_long value = mode;
|
||||
return ioctlsocket(s, FIONBIO, &value) != SOCKET_ERROR;
|
||||
}
|
523
crypto/bio/bf_buff.c
Normal file
523
crypto/bio/bf_buff.c
Normal file
@@ -0,0 +1,523 @@
|
||||
/* $OpenBSD: bf_buff.c,v 1.28 2023/07/05 21:23:37 beck Exp $ */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "bio_local.h"
|
||||
|
||||
static int buffer_write(BIO *h, const char *buf, int num);
|
||||
static int buffer_read(BIO *h, char *buf, int size);
|
||||
static int buffer_puts(BIO *h, const char *str);
|
||||
static int buffer_gets(BIO *h, char *str, int size);
|
||||
static long buffer_ctrl(BIO *h, int cmd, long arg1, void *arg2);
|
||||
static int buffer_new(BIO *h);
|
||||
static int buffer_free(BIO *data);
|
||||
static long buffer_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp);
|
||||
#define DEFAULT_BUFFER_SIZE 4096
|
||||
|
||||
static const BIO_METHOD methods_buffer = {
|
||||
.type = BIO_TYPE_BUFFER,
|
||||
.name = "buffer",
|
||||
.bwrite = buffer_write,
|
||||
.bread = buffer_read,
|
||||
.bputs = buffer_puts,
|
||||
.bgets = buffer_gets,
|
||||
.ctrl = buffer_ctrl,
|
||||
.create = buffer_new,
|
||||
.destroy = buffer_free,
|
||||
.callback_ctrl = buffer_callback_ctrl
|
||||
};
|
||||
|
||||
const BIO_METHOD *
|
||||
BIO_f_buffer(void)
|
||||
{
|
||||
return (&methods_buffer);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_f_buffer);
|
||||
|
||||
static int
|
||||
buffer_new(BIO *bi)
|
||||
{
|
||||
BIO_F_BUFFER_CTX *ctx;
|
||||
|
||||
ctx = malloc(sizeof(BIO_F_BUFFER_CTX));
|
||||
if (ctx == NULL)
|
||||
return (0);
|
||||
ctx->ibuf = malloc(DEFAULT_BUFFER_SIZE);
|
||||
if (ctx->ibuf == NULL) {
|
||||
free(ctx);
|
||||
return (0);
|
||||
}
|
||||
ctx->obuf = malloc(DEFAULT_BUFFER_SIZE);
|
||||
if (ctx->obuf == NULL) {
|
||||
free(ctx->ibuf);
|
||||
free(ctx);
|
||||
return (0);
|
||||
}
|
||||
ctx->ibuf_size = DEFAULT_BUFFER_SIZE;
|
||||
ctx->obuf_size = DEFAULT_BUFFER_SIZE;
|
||||
ctx->ibuf_len = 0;
|
||||
ctx->ibuf_off = 0;
|
||||
ctx->obuf_len = 0;
|
||||
ctx->obuf_off = 0;
|
||||
|
||||
bi->init = 1;
|
||||
bi->ptr = (char *)ctx;
|
||||
bi->flags = 0;
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
buffer_free(BIO *a)
|
||||
{
|
||||
BIO_F_BUFFER_CTX *b;
|
||||
|
||||
if (a == NULL)
|
||||
return (0);
|
||||
b = (BIO_F_BUFFER_CTX *)a->ptr;
|
||||
free(b->ibuf);
|
||||
free(b->obuf);
|
||||
free(a->ptr);
|
||||
a->ptr = NULL;
|
||||
a->init = 0;
|
||||
a->flags = 0;
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
buffer_read(BIO *b, char *out, int outl)
|
||||
{
|
||||
int i, num = 0;
|
||||
BIO_F_BUFFER_CTX *ctx;
|
||||
|
||||
if (out == NULL)
|
||||
return (0);
|
||||
ctx = (BIO_F_BUFFER_CTX *)b->ptr;
|
||||
|
||||
if ((ctx == NULL) || (b->next_bio == NULL))
|
||||
return (0);
|
||||
num = 0;
|
||||
BIO_clear_retry_flags(b);
|
||||
|
||||
start:
|
||||
i = ctx->ibuf_len;
|
||||
/* If there is stuff left over, grab it */
|
||||
if (i != 0) {
|
||||
if (i > outl)
|
||||
i = outl;
|
||||
memcpy(out, &(ctx->ibuf[ctx->ibuf_off]), i);
|
||||
ctx->ibuf_off += i;
|
||||
ctx->ibuf_len -= i;
|
||||
num += i;
|
||||
if (outl == i)
|
||||
return (num);
|
||||
outl -= i;
|
||||
out += i;
|
||||
}
|
||||
|
||||
/* We may have done a partial read. try to do more.
|
||||
* We have nothing in the buffer.
|
||||
* If we get an error and have read some data, just return it
|
||||
* and let them retry to get the error again.
|
||||
* copy direct to parent address space */
|
||||
if (outl > ctx->ibuf_size) {
|
||||
for (;;) {
|
||||
i = BIO_read(b->next_bio, out, outl);
|
||||
if (i <= 0) {
|
||||
BIO_copy_next_retry(b);
|
||||
if (i < 0)
|
||||
return ((num > 0) ? num : i);
|
||||
if (i == 0)
|
||||
return (num);
|
||||
}
|
||||
num += i;
|
||||
if (outl == i)
|
||||
return (num);
|
||||
out += i;
|
||||
outl -= i;
|
||||
}
|
||||
}
|
||||
/* else */
|
||||
|
||||
/* we are going to be doing some buffering */
|
||||
i = BIO_read(b->next_bio, ctx->ibuf, ctx->ibuf_size);
|
||||
if (i <= 0) {
|
||||
BIO_copy_next_retry(b);
|
||||
if (i < 0)
|
||||
return ((num > 0) ? num : i);
|
||||
if (i == 0)
|
||||
return (num);
|
||||
}
|
||||
ctx->ibuf_off = 0;
|
||||
ctx->ibuf_len = i;
|
||||
|
||||
/* Lets re-read using ourselves :-) */
|
||||
goto start;
|
||||
}
|
||||
|
||||
static int
|
||||
buffer_write(BIO *b, const char *in, int inl)
|
||||
{
|
||||
int i, num = 0;
|
||||
BIO_F_BUFFER_CTX *ctx;
|
||||
|
||||
if ((in == NULL) || (inl <= 0))
|
||||
return (0);
|
||||
ctx = (BIO_F_BUFFER_CTX *)b->ptr;
|
||||
if ((ctx == NULL) || (b->next_bio == NULL))
|
||||
return (0);
|
||||
|
||||
BIO_clear_retry_flags(b);
|
||||
start:
|
||||
i = ctx->obuf_size - (ctx->obuf_len + ctx->obuf_off);
|
||||
/* add to buffer and return */
|
||||
if (i >= inl) {
|
||||
memcpy(&(ctx->obuf[ctx->obuf_off + ctx->obuf_len]), in, inl);
|
||||
ctx->obuf_len += inl;
|
||||
return (num + inl);
|
||||
}
|
||||
/* else */
|
||||
/* stuff already in buffer, so add to it first, then flush */
|
||||
if (ctx->obuf_len != 0) {
|
||||
if (i > 0) /* lets fill it up if we can */
|
||||
{
|
||||
memcpy(&(ctx->obuf[ctx->obuf_off + ctx->obuf_len]), in, i);
|
||||
in += i;
|
||||
inl -= i;
|
||||
num += i;
|
||||
ctx->obuf_len += i;
|
||||
}
|
||||
/* we now have a full buffer needing flushing */
|
||||
for (;;) {
|
||||
i = BIO_write(b->next_bio, &(ctx->obuf[ctx->obuf_off]),
|
||||
ctx->obuf_len);
|
||||
if (i <= 0) {
|
||||
BIO_copy_next_retry(b);
|
||||
|
||||
if (i < 0)
|
||||
return ((num > 0) ? num : i);
|
||||
if (i == 0)
|
||||
return (num);
|
||||
}
|
||||
ctx->obuf_off += i;
|
||||
ctx->obuf_len -= i;
|
||||
if (ctx->obuf_len == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* we only get here if the buffer has been flushed and we
|
||||
* still have stuff to write */
|
||||
ctx->obuf_off = 0;
|
||||
|
||||
/* we now have inl bytes to write */
|
||||
while (inl >= ctx->obuf_size) {
|
||||
i = BIO_write(b->next_bio, in, inl);
|
||||
if (i <= 0) {
|
||||
BIO_copy_next_retry(b);
|
||||
if (i < 0)
|
||||
return ((num > 0) ? num : i);
|
||||
if (i == 0)
|
||||
return (num);
|
||||
}
|
||||
num += i;
|
||||
in += i;
|
||||
inl -= i;
|
||||
if (inl == 0)
|
||||
return (num);
|
||||
}
|
||||
|
||||
/* copy the rest into the buffer since we have only a small
|
||||
* amount left */
|
||||
goto start;
|
||||
}
|
||||
|
||||
static long
|
||||
buffer_ctrl(BIO *b, int cmd, long num, void *ptr)
|
||||
{
|
||||
BIO *dbio;
|
||||
BIO_F_BUFFER_CTX *ctx;
|
||||
long ret = 1;
|
||||
char *p1, *p2;
|
||||
int r, i, *ip;
|
||||
int ibs, obs;
|
||||
|
||||
ctx = (BIO_F_BUFFER_CTX *)b->ptr;
|
||||
|
||||
switch (cmd) {
|
||||
case BIO_CTRL_RESET:
|
||||
ctx->ibuf_off = 0;
|
||||
ctx->ibuf_len = 0;
|
||||
ctx->obuf_off = 0;
|
||||
ctx->obuf_len = 0;
|
||||
if (b->next_bio == NULL)
|
||||
return (0);
|
||||
ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
|
||||
break;
|
||||
case BIO_CTRL_INFO:
|
||||
ret = (long)ctx->obuf_len;
|
||||
break;
|
||||
case BIO_C_GET_BUFF_NUM_LINES:
|
||||
ret = 0;
|
||||
p1 = ctx->ibuf;
|
||||
for (i = 0; i < ctx->ibuf_len; i++) {
|
||||
if (p1[ctx->ibuf_off + i] == '\n')
|
||||
ret++;
|
||||
}
|
||||
break;
|
||||
case BIO_CTRL_WPENDING:
|
||||
ret = (long)ctx->obuf_len;
|
||||
if (ret == 0) {
|
||||
if (b->next_bio == NULL)
|
||||
return (0);
|
||||
ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
|
||||
}
|
||||
break;
|
||||
case BIO_CTRL_PENDING:
|
||||
ret = (long)ctx->ibuf_len;
|
||||
if (ret == 0) {
|
||||
if (b->next_bio == NULL)
|
||||
return (0);
|
||||
ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
|
||||
}
|
||||
break;
|
||||
case BIO_C_SET_BUFF_READ_DATA:
|
||||
if (num > ctx->ibuf_size) {
|
||||
p1 = malloc(num);
|
||||
if (p1 == NULL)
|
||||
goto malloc_error;
|
||||
free(ctx->ibuf);
|
||||
ctx->ibuf = p1;
|
||||
}
|
||||
ctx->ibuf_off = 0;
|
||||
ctx->ibuf_len = (int)num;
|
||||
memcpy(ctx->ibuf, ptr, num);
|
||||
ret = 1;
|
||||
break;
|
||||
case BIO_C_SET_BUFF_SIZE:
|
||||
if (ptr != NULL) {
|
||||
ip = (int *)ptr;
|
||||
if (*ip == 0) {
|
||||
ibs = (int)num;
|
||||
obs = ctx->obuf_size;
|
||||
}
|
||||
else /* if (*ip == 1) */
|
||||
{
|
||||
ibs = ctx->ibuf_size;
|
||||
obs = (int)num;
|
||||
}
|
||||
} else {
|
||||
ibs = (int)num;
|
||||
obs = (int)num;
|
||||
}
|
||||
p1 = ctx->ibuf;
|
||||
p2 = ctx->obuf;
|
||||
if ((ibs > DEFAULT_BUFFER_SIZE) && (ibs != ctx->ibuf_size)) {
|
||||
p1 = malloc(num);
|
||||
if (p1 == NULL)
|
||||
goto malloc_error;
|
||||
}
|
||||
if ((obs > DEFAULT_BUFFER_SIZE) && (obs != ctx->obuf_size)) {
|
||||
p2 = malloc(num);
|
||||
if (p2 == NULL) {
|
||||
if (p1 != ctx->ibuf)
|
||||
free(p1);
|
||||
goto malloc_error;
|
||||
}
|
||||
}
|
||||
if (ctx->ibuf != p1) {
|
||||
free(ctx->ibuf);
|
||||
ctx->ibuf = p1;
|
||||
ctx->ibuf_off = 0;
|
||||
ctx->ibuf_len = 0;
|
||||
ctx->ibuf_size = ibs;
|
||||
}
|
||||
if (ctx->obuf != p2) {
|
||||
free(ctx->obuf);
|
||||
ctx->obuf = p2;
|
||||
ctx->obuf_off = 0;
|
||||
ctx->obuf_len = 0;
|
||||
ctx->obuf_size = obs;
|
||||
}
|
||||
break;
|
||||
case BIO_C_DO_STATE_MACHINE:
|
||||
if (b->next_bio == NULL)
|
||||
return (0);
|
||||
BIO_clear_retry_flags(b);
|
||||
ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
|
||||
BIO_copy_next_retry(b);
|
||||
break;
|
||||
|
||||
case BIO_CTRL_FLUSH:
|
||||
if (b->next_bio == NULL)
|
||||
return (0);
|
||||
if (ctx->obuf_len <= 0) {
|
||||
ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
|
||||
break;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
BIO_clear_retry_flags(b);
|
||||
if (ctx->obuf_len > 0) {
|
||||
r = BIO_write(b->next_bio,
|
||||
&(ctx->obuf[ctx->obuf_off]),
|
||||
ctx->obuf_len);
|
||||
BIO_copy_next_retry(b);
|
||||
if (r <= 0)
|
||||
return ((long)r);
|
||||
ctx->obuf_off += r;
|
||||
ctx->obuf_len -= r;
|
||||
} else {
|
||||
ctx->obuf_len = 0;
|
||||
ctx->obuf_off = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
|
||||
break;
|
||||
case BIO_CTRL_DUP:
|
||||
dbio = (BIO *)ptr;
|
||||
if (!BIO_set_read_buffer_size(dbio, ctx->ibuf_size) ||
|
||||
!BIO_set_write_buffer_size(dbio, ctx->obuf_size))
|
||||
ret = 0;
|
||||
break;
|
||||
default:
|
||||
if (b->next_bio == NULL)
|
||||
return (0);
|
||||
ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
|
||||
break;
|
||||
}
|
||||
return (ret);
|
||||
malloc_error:
|
||||
BIOerror(ERR_R_MALLOC_FAILURE);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static long
|
||||
buffer_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
|
||||
{
|
||||
long ret = 1;
|
||||
|
||||
if (b->next_bio == NULL)
|
||||
return (0);
|
||||
switch (cmd) {
|
||||
default:
|
||||
ret = BIO_callback_ctrl(b->next_bio, cmd, fp);
|
||||
break;
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
buffer_gets(BIO *b, char *buf, int size)
|
||||
{
|
||||
BIO_F_BUFFER_CTX *ctx;
|
||||
int num = 0, i, flag;
|
||||
char *p;
|
||||
|
||||
ctx = (BIO_F_BUFFER_CTX *)b->ptr;
|
||||
size--; /* reserve space for a '\0' */
|
||||
BIO_clear_retry_flags(b);
|
||||
|
||||
for (;;) {
|
||||
if (ctx->ibuf_len > 0) {
|
||||
p = &(ctx->ibuf[ctx->ibuf_off]);
|
||||
flag = 0;
|
||||
for (i = 0; (i < ctx->ibuf_len) && (i < size); i++) {
|
||||
*(buf++) = p[i];
|
||||
if (p[i] == '\n') {
|
||||
flag = 1;
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
num += i;
|
||||
size -= i;
|
||||
ctx->ibuf_len -= i;
|
||||
ctx->ibuf_off += i;
|
||||
if (flag || size == 0) {
|
||||
*buf = '\0';
|
||||
return (num);
|
||||
}
|
||||
}
|
||||
else /* read another chunk */
|
||||
{
|
||||
i = BIO_read(b->next_bio, ctx->ibuf, ctx->ibuf_size);
|
||||
if (i <= 0) {
|
||||
BIO_copy_next_retry(b);
|
||||
*buf = '\0';
|
||||
if (i < 0)
|
||||
return ((num > 0) ? num : i);
|
||||
if (i == 0)
|
||||
return (num);
|
||||
}
|
||||
ctx->ibuf_len = i;
|
||||
ctx->ibuf_off = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
buffer_puts(BIO *b, const char *str)
|
||||
{
|
||||
return (buffer_write(b, str, strlen(str)));
|
||||
}
|
255
crypto/bio/bf_nbio.c
Normal file
255
crypto/bio/bf_nbio.c
Normal file
@@ -0,0 +1,255 @@
|
||||
/* $OpenBSD: bf_nbio.c,v 1.23 2023/07/05 21:23:37 beck Exp $ */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <openssl/bio.h>
|
||||
|
||||
#include "bio_local.h"
|
||||
|
||||
/* BIO_put and BIO_get both add to the digest,
|
||||
* BIO_gets returns the digest */
|
||||
|
||||
static int nbiof_write(BIO *h, const char *buf, int num);
|
||||
static int nbiof_read(BIO *h, char *buf, int size);
|
||||
static int nbiof_puts(BIO *h, const char *str);
|
||||
static int nbiof_gets(BIO *h, char *str, int size);
|
||||
static long nbiof_ctrl(BIO *h, int cmd, long arg1, void *arg2);
|
||||
static int nbiof_new(BIO *h);
|
||||
static int nbiof_free(BIO *data);
|
||||
static long nbiof_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp);
|
||||
|
||||
typedef struct nbio_test_st {
|
||||
/* only set if we sent a 'should retry' error */
|
||||
int lrn;
|
||||
int lwn;
|
||||
} NBIO_TEST;
|
||||
|
||||
static const BIO_METHOD methods_nbiof = {
|
||||
.type = BIO_TYPE_NBIO_TEST,
|
||||
.name = "non-blocking IO test filter",
|
||||
.bwrite = nbiof_write,
|
||||
.bread = nbiof_read,
|
||||
.bputs = nbiof_puts,
|
||||
.bgets = nbiof_gets,
|
||||
.ctrl = nbiof_ctrl,
|
||||
.create = nbiof_new,
|
||||
.destroy = nbiof_free,
|
||||
.callback_ctrl = nbiof_callback_ctrl
|
||||
};
|
||||
|
||||
const BIO_METHOD *
|
||||
BIO_f_nbio_test(void)
|
||||
{
|
||||
return (&methods_nbiof);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_f_nbio_test);
|
||||
|
||||
static int
|
||||
nbiof_new(BIO *bi)
|
||||
{
|
||||
NBIO_TEST *nt;
|
||||
|
||||
if (!(nt = malloc(sizeof(NBIO_TEST))))
|
||||
return (0);
|
||||
nt->lrn = -1;
|
||||
nt->lwn = -1;
|
||||
bi->ptr = (char *)nt;
|
||||
bi->init = 1;
|
||||
bi->flags = 0;
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
nbiof_free(BIO *a)
|
||||
{
|
||||
if (a == NULL)
|
||||
return (0);
|
||||
free(a->ptr);
|
||||
a->ptr = NULL;
|
||||
a->init = 0;
|
||||
a->flags = 0;
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
nbiof_read(BIO *b, char *out, int outl)
|
||||
{
|
||||
int ret = 0;
|
||||
int num;
|
||||
unsigned char n;
|
||||
|
||||
if (out == NULL)
|
||||
return (0);
|
||||
if (b->next_bio == NULL)
|
||||
return (0);
|
||||
|
||||
BIO_clear_retry_flags(b);
|
||||
|
||||
arc4random_buf(&n, 1);
|
||||
num = (n & 0x07);
|
||||
|
||||
if (outl > num)
|
||||
outl = num;
|
||||
|
||||
if (num == 0) {
|
||||
ret = -1;
|
||||
BIO_set_retry_read(b);
|
||||
} else {
|
||||
ret = BIO_read(b->next_bio, out, outl);
|
||||
if (ret < 0)
|
||||
BIO_copy_next_retry(b);
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
nbiof_write(BIO *b, const char *in, int inl)
|
||||
{
|
||||
NBIO_TEST *nt;
|
||||
int ret = 0;
|
||||
int num;
|
||||
unsigned char n;
|
||||
|
||||
if ((in == NULL) || (inl <= 0))
|
||||
return (0);
|
||||
if (b->next_bio == NULL)
|
||||
return (0);
|
||||
nt = (NBIO_TEST *)b->ptr;
|
||||
|
||||
BIO_clear_retry_flags(b);
|
||||
|
||||
if (nt->lwn > 0) {
|
||||
num = nt->lwn;
|
||||
nt->lwn = 0;
|
||||
} else {
|
||||
arc4random_buf(&n, 1);
|
||||
num = (n&7);
|
||||
}
|
||||
|
||||
if (inl > num)
|
||||
inl = num;
|
||||
|
||||
if (num == 0) {
|
||||
ret = -1;
|
||||
BIO_set_retry_write(b);
|
||||
} else {
|
||||
ret = BIO_write(b->next_bio, in, inl);
|
||||
if (ret < 0) {
|
||||
BIO_copy_next_retry(b);
|
||||
nt->lwn = inl;
|
||||
}
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static long
|
||||
nbiof_ctrl(BIO *b, int cmd, long num, void *ptr)
|
||||
{
|
||||
long ret;
|
||||
|
||||
if (b->next_bio == NULL)
|
||||
return (0);
|
||||
switch (cmd) {
|
||||
case BIO_C_DO_STATE_MACHINE:
|
||||
BIO_clear_retry_flags(b);
|
||||
ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
|
||||
BIO_copy_next_retry(b);
|
||||
break;
|
||||
case BIO_CTRL_DUP:
|
||||
ret = 0L;
|
||||
break;
|
||||
default:
|
||||
ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
|
||||
break;
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static long
|
||||
nbiof_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
|
||||
{
|
||||
long ret = 1;
|
||||
|
||||
if (b->next_bio == NULL)
|
||||
return (0);
|
||||
switch (cmd) {
|
||||
default:
|
||||
ret = BIO_callback_ctrl(b->next_bio, cmd, fp);
|
||||
break;
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
nbiof_gets(BIO *bp, char *buf, int size)
|
||||
{
|
||||
if (bp->next_bio == NULL)
|
||||
return (0);
|
||||
return (BIO_gets(bp->next_bio, buf, size));
|
||||
}
|
||||
|
||||
static int
|
||||
nbiof_puts(BIO *bp, const char *str)
|
||||
{
|
||||
if (bp->next_bio == NULL)
|
||||
return (0);
|
||||
return (BIO_puts(bp->next_bio, str));
|
||||
}
|
199
crypto/bio/bf_null.c
Normal file
199
crypto/bio/bf_null.c
Normal file
@@ -0,0 +1,199 @@
|
||||
/* $OpenBSD: bf_null.c,v 1.15 2023/07/05 21:23:37 beck Exp $ */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <openssl/bio.h>
|
||||
|
||||
#include "bio_local.h"
|
||||
|
||||
/* BIO_put and BIO_get both add to the digest,
|
||||
* BIO_gets returns the digest */
|
||||
|
||||
static int nullf_write(BIO *h, const char *buf, int num);
|
||||
static int nullf_read(BIO *h, char *buf, int size);
|
||||
static int nullf_puts(BIO *h, const char *str);
|
||||
static int nullf_gets(BIO *h, char *str, int size);
|
||||
static long nullf_ctrl(BIO *h, int cmd, long arg1, void *arg2);
|
||||
static int nullf_new(BIO *h);
|
||||
static int nullf_free(BIO *data);
|
||||
static long nullf_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp);
|
||||
|
||||
static const BIO_METHOD methods_nullf = {
|
||||
.type = BIO_TYPE_NULL_FILTER,
|
||||
.name = "NULL filter",
|
||||
.bwrite = nullf_write,
|
||||
.bread = nullf_read,
|
||||
.bputs = nullf_puts,
|
||||
.bgets = nullf_gets,
|
||||
.ctrl = nullf_ctrl,
|
||||
.create = nullf_new,
|
||||
.destroy = nullf_free,
|
||||
.callback_ctrl = nullf_callback_ctrl
|
||||
};
|
||||
|
||||
const BIO_METHOD *
|
||||
BIO_f_null(void)
|
||||
{
|
||||
return (&methods_nullf);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_f_null);
|
||||
|
||||
static int
|
||||
nullf_new(BIO *bi)
|
||||
{
|
||||
bi->init = 1;
|
||||
bi->ptr = NULL;
|
||||
bi->flags = 0;
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
nullf_free(BIO *a)
|
||||
{
|
||||
if (a == NULL)
|
||||
return (0);
|
||||
/* a->ptr=NULL;
|
||||
a->init=0;
|
||||
a->flags=0;*/
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
nullf_read(BIO *b, char *out, int outl)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (out == NULL)
|
||||
return (0);
|
||||
if (b->next_bio == NULL)
|
||||
return (0);
|
||||
ret = BIO_read(b->next_bio, out, outl);
|
||||
BIO_clear_retry_flags(b);
|
||||
BIO_copy_next_retry(b);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
nullf_write(BIO *b, const char *in, int inl)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if ((in == NULL) || (inl <= 0))
|
||||
return (0);
|
||||
if (b->next_bio == NULL)
|
||||
return (0);
|
||||
ret = BIO_write(b->next_bio, in, inl);
|
||||
BIO_clear_retry_flags(b);
|
||||
BIO_copy_next_retry(b);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static long
|
||||
nullf_ctrl(BIO *b, int cmd, long num, void *ptr)
|
||||
{
|
||||
long ret;
|
||||
|
||||
if (b->next_bio == NULL)
|
||||
return (0);
|
||||
switch (cmd) {
|
||||
case BIO_C_DO_STATE_MACHINE:
|
||||
BIO_clear_retry_flags(b);
|
||||
ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
|
||||
BIO_copy_next_retry(b);
|
||||
break;
|
||||
case BIO_CTRL_DUP:
|
||||
ret = 0L;
|
||||
break;
|
||||
default:
|
||||
ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static long
|
||||
nullf_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
|
||||
{
|
||||
long ret = 1;
|
||||
|
||||
if (b->next_bio == NULL)
|
||||
return (0);
|
||||
switch (cmd) {
|
||||
default:
|
||||
ret = BIO_callback_ctrl(b->next_bio, cmd, fp);
|
||||
break;
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
nullf_gets(BIO *bp, char *buf, int size)
|
||||
{
|
||||
if (bp->next_bio == NULL)
|
||||
return (0);
|
||||
return (BIO_gets(bp->next_bio, buf, size));
|
||||
}
|
||||
|
||||
static int
|
||||
nullf_puts(BIO *bp, const char *str)
|
||||
{
|
||||
if (bp->next_bio == NULL)
|
||||
return (0);
|
||||
return (BIO_puts(bp->next_bio, str));
|
||||
}
|
156
crypto/bio/bio_cb.c
Normal file
156
crypto/bio/bio_cb.c
Normal file
@@ -0,0 +1,156 @@
|
||||
/* $OpenBSD: bio_cb.c,v 1.19 2023/07/05 21:23:37 beck Exp $ */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/bio.h>
|
||||
|
||||
#include "bio_local.h"
|
||||
|
||||
long
|
||||
BIO_debug_callback(BIO *bio, int cmd, const char *argp, int argi, long argl,
|
||||
long ret)
|
||||
{
|
||||
BIO *b;
|
||||
char buf[256];
|
||||
char *p;
|
||||
int nbuf;
|
||||
long r = 1;
|
||||
size_t p_maxlen;
|
||||
|
||||
if (BIO_CB_RETURN & cmd)
|
||||
r = ret;
|
||||
|
||||
nbuf = snprintf(buf, sizeof(buf), "BIO[%p]: ", bio);
|
||||
if (nbuf < 0)
|
||||
nbuf = 0; /* Ignore error; continue printing. */
|
||||
if (nbuf >= sizeof(buf))
|
||||
goto out;
|
||||
|
||||
p = buf + nbuf;
|
||||
p_maxlen = sizeof(buf) - nbuf;
|
||||
|
||||
switch (cmd) {
|
||||
case BIO_CB_FREE:
|
||||
snprintf(p, p_maxlen, "Free - %s\n", bio->method->name);
|
||||
break;
|
||||
case BIO_CB_READ:
|
||||
if (bio->method->type & BIO_TYPE_DESCRIPTOR)
|
||||
snprintf(p, p_maxlen,
|
||||
"read(%d,%lu) - %s fd=%d\n",
|
||||
bio->num, (unsigned long)argi,
|
||||
bio->method->name, bio->num);
|
||||
else
|
||||
snprintf(p, p_maxlen, "read(%d,%lu) - %s\n",
|
||||
bio->num, (unsigned long)argi, bio->method->name);
|
||||
break;
|
||||
case BIO_CB_WRITE:
|
||||
if (bio->method->type & BIO_TYPE_DESCRIPTOR)
|
||||
snprintf(p, p_maxlen,
|
||||
"write(%d,%lu) - %s fd=%d\n",
|
||||
bio->num, (unsigned long)argi,
|
||||
bio->method->name, bio->num);
|
||||
else
|
||||
snprintf(p, p_maxlen, "write(%d,%lu) - %s\n",
|
||||
bio->num, (unsigned long)argi, bio->method->name);
|
||||
break;
|
||||
case BIO_CB_PUTS:
|
||||
snprintf(p, p_maxlen,
|
||||
"puts() - %s\n", bio->method->name);
|
||||
break;
|
||||
case BIO_CB_GETS:
|
||||
snprintf(p, p_maxlen, "gets(%lu) - %s\n",
|
||||
(unsigned long)argi, bio->method->name);
|
||||
break;
|
||||
case BIO_CB_CTRL:
|
||||
snprintf(p, p_maxlen, "ctrl(%lu) - %s\n",
|
||||
(unsigned long)argi, bio->method->name);
|
||||
break;
|
||||
case BIO_CB_RETURN|BIO_CB_READ:
|
||||
snprintf(p, p_maxlen, "read return %ld\n", ret);
|
||||
break;
|
||||
case BIO_CB_RETURN|BIO_CB_WRITE:
|
||||
snprintf(p, p_maxlen, "write return %ld\n", ret);
|
||||
break;
|
||||
case BIO_CB_RETURN|BIO_CB_GETS:
|
||||
snprintf(p, p_maxlen, "gets return %ld\n", ret);
|
||||
break;
|
||||
case BIO_CB_RETURN|BIO_CB_PUTS:
|
||||
snprintf(p, p_maxlen, "puts return %ld\n", ret);
|
||||
break;
|
||||
case BIO_CB_RETURN|BIO_CB_CTRL:
|
||||
snprintf(p, p_maxlen, "ctrl return %ld\n", ret);
|
||||
break;
|
||||
default:
|
||||
snprintf(p, p_maxlen,
|
||||
"bio callback - unknown type (%d)\n", cmd);
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
b = (BIO *)bio->cb_arg;
|
||||
if (b != NULL)
|
||||
BIO_write(b, buf, strlen(buf));
|
||||
else
|
||||
fputs(buf, stderr);
|
||||
return (r);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_debug_callback);
|
120
crypto/bio/bio_err.c
Normal file
120
crypto/bio/bio_err.c
Normal file
@@ -0,0 +1,120 @@
|
||||
/* $OpenBSD: bio_err.c,v 1.20 2023/07/05 21:23:37 beck Exp $ */
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1999-2011 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <openssl/opensslconf.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/bio.h>
|
||||
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
|
||||
#define ERR_FUNC(func) ERR_PACK(ERR_LIB_BIO,func,0)
|
||||
#define ERR_REASON(reason) ERR_PACK(ERR_LIB_BIO,0,reason)
|
||||
|
||||
static ERR_STRING_DATA BIO_str_functs[] = {
|
||||
{ERR_FUNC(0xfff), "CRYPTO_internal"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
static ERR_STRING_DATA BIO_str_reasons[] = {
|
||||
{ERR_REASON(BIO_R_ACCEPT_ERROR) , "accept error"},
|
||||
{ERR_REASON(BIO_R_BAD_FOPEN_MODE) , "bad fopen mode"},
|
||||
{ERR_REASON(BIO_R_BAD_HOSTNAME_LOOKUP) , "bad hostname lookup"},
|
||||
{ERR_REASON(BIO_R_BROKEN_PIPE) , "broken pipe"},
|
||||
{ERR_REASON(BIO_R_CONNECT_ERROR) , "connect error"},
|
||||
{ERR_REASON(BIO_R_EOF_ON_MEMORY_BIO) , "EOF on memory BIO"},
|
||||
{ERR_REASON(BIO_R_ERROR_SETTING_NBIO) , "error setting nbio"},
|
||||
{ERR_REASON(BIO_R_ERROR_SETTING_NBIO_ON_ACCEPTED_SOCKET), "error setting nbio on accepted socket"},
|
||||
{ERR_REASON(BIO_R_ERROR_SETTING_NBIO_ON_ACCEPT_SOCKET), "error setting nbio on accept socket"},
|
||||
{ERR_REASON(BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET), "gethostbyname addr is not af inet"},
|
||||
{ERR_REASON(BIO_R_INVALID_ARGUMENT) , "invalid argument"},
|
||||
{ERR_REASON(BIO_R_INVALID_IP_ADDRESS) , "invalid ip address"},
|
||||
{ERR_REASON(BIO_R_INVALID_PORT_NUMBER) , "invalid port number"},
|
||||
{ERR_REASON(BIO_R_IN_USE) , "in use"},
|
||||
{ERR_REASON(BIO_R_KEEPALIVE) , "keepalive"},
|
||||
{ERR_REASON(BIO_R_LENGTH_TOO_LONG) , "too long"},
|
||||
{ERR_REASON(BIO_R_NBIO_CONNECT_ERROR) , "nbio connect error"},
|
||||
{ERR_REASON(BIO_R_NO_ACCEPT_PORT_SPECIFIED), "no accept port specified"},
|
||||
{ERR_REASON(BIO_R_NO_HOSTNAME_SPECIFIED) , "no hostname specified"},
|
||||
{ERR_REASON(BIO_R_NO_PORT_DEFINED) , "no port defined"},
|
||||
{ERR_REASON(BIO_R_NO_PORT_SPECIFIED) , "no port specified"},
|
||||
{ERR_REASON(BIO_R_NO_SUCH_FILE) , "no such file"},
|
||||
{ERR_REASON(BIO_R_NULL_PARAMETER) , "null parameter"},
|
||||
{ERR_REASON(BIO_R_TAG_MISMATCH) , "tag mismatch"},
|
||||
{ERR_REASON(BIO_R_UNABLE_TO_BIND_SOCKET) , "unable to bind socket"},
|
||||
{ERR_REASON(BIO_R_UNABLE_TO_CREATE_SOCKET), "unable to create socket"},
|
||||
{ERR_REASON(BIO_R_UNABLE_TO_LISTEN_SOCKET), "unable to listen socket"},
|
||||
{ERR_REASON(BIO_R_UNINITIALIZED) , "uninitialized"},
|
||||
{ERR_REASON(BIO_R_UNSUPPORTED_METHOD) , "unsupported method"},
|
||||
{ERR_REASON(BIO_R_WRITE_TO_READ_ONLY_BIO), "write to read only BIO"},
|
||||
{ERR_REASON(BIO_R_WSASTARTUP) , "WSAStartup"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
ERR_load_BIO_strings(void)
|
||||
{
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
if (ERR_func_error_string(BIO_str_functs[0].error) == NULL) {
|
||||
ERR_load_strings(0, BIO_str_functs);
|
||||
ERR_load_strings(0, BIO_str_reasons);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
LCRYPTO_ALIAS(ERR_load_BIO_strings);
|
904
crypto/bio/bio_lib.c
Normal file
904
crypto/bio/bio_lib.c
Normal file
@@ -0,0 +1,904 @@
|
||||
/* $OpenBSD: bio_lib.c,v 1.48 2023/08/07 10:58:56 tb Exp $ */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/stack.h>
|
||||
|
||||
#include "bio_local.h"
|
||||
|
||||
/*
|
||||
* Helper function to work out whether to call the new style callback or the old
|
||||
* one, and translate between the two.
|
||||
*
|
||||
* This has a long return type for consistency with the old callback. Similarly
|
||||
* for the "long" used for "inret"
|
||||
*/
|
||||
static long
|
||||
bio_call_callback(BIO *b, int oper, const char *argp, size_t len, int argi,
|
||||
long argl, long inret, size_t *processed)
|
||||
{
|
||||
long ret;
|
||||
int bareoper;
|
||||
|
||||
if (b->callback_ex != NULL)
|
||||
return b->callback_ex(b, oper, argp, len, argi, argl, inret,
|
||||
processed);
|
||||
|
||||
/*
|
||||
* We have an old style callback, so we will have to do nasty casts and
|
||||
* check for overflows.
|
||||
*/
|
||||
|
||||
bareoper = oper & ~BIO_CB_RETURN;
|
||||
|
||||
if (bareoper == BIO_CB_READ || bareoper == BIO_CB_WRITE ||
|
||||
bareoper == BIO_CB_GETS) {
|
||||
/* In this case len is set and should be used instead of argi. */
|
||||
if (len > INT_MAX)
|
||||
return -1;
|
||||
argi = (int)len;
|
||||
}
|
||||
|
||||
if (inret > 0 && (oper & BIO_CB_RETURN) && bareoper != BIO_CB_CTRL) {
|
||||
if (*processed > INT_MAX)
|
||||
return -1;
|
||||
inret = *processed;
|
||||
}
|
||||
|
||||
ret = b->callback(b, oper, argp, argi, argl, inret);
|
||||
|
||||
if (ret > 0 && (oper & BIO_CB_RETURN) && bareoper != BIO_CB_CTRL) {
|
||||
*processed = (size_t)ret;
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
BIO_get_new_index(void)
|
||||
{
|
||||
static int bio_type_index = BIO_TYPE_START;
|
||||
int index;
|
||||
|
||||
/* The index will collide with the BIO flag bits if it exceeds 255. */
|
||||
index = CRYPTO_add(&bio_type_index, 1, CRYPTO_LOCK_BIO);
|
||||
if (index > 255)
|
||||
return -1;
|
||||
|
||||
return index;
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_get_new_index);
|
||||
|
||||
BIO *
|
||||
BIO_new(const BIO_METHOD *method)
|
||||
{
|
||||
BIO *ret = NULL;
|
||||
|
||||
/* XXX calloc */
|
||||
ret = malloc(sizeof(BIO));
|
||||
if (ret == NULL) {
|
||||
BIOerror(ERR_R_MALLOC_FAILURE);
|
||||
return (NULL);
|
||||
}
|
||||
if (!BIO_set(ret, method)) {
|
||||
free(ret);
|
||||
ret = NULL;
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_new);
|
||||
|
||||
int
|
||||
BIO_set(BIO *bio, const BIO_METHOD *method)
|
||||
{
|
||||
bio->method = method;
|
||||
bio->callback = NULL;
|
||||
bio->callback_ex = NULL;
|
||||
bio->cb_arg = NULL;
|
||||
bio->init = 0;
|
||||
bio->shutdown = 1;
|
||||
bio->flags = 0;
|
||||
bio->retry_reason = 0;
|
||||
bio->num = 0;
|
||||
bio->ptr = NULL;
|
||||
bio->prev_bio = NULL;
|
||||
bio->next_bio = NULL;
|
||||
bio->references = 1;
|
||||
bio->num_read = 0L;
|
||||
bio->num_write = 0L;
|
||||
CRYPTO_new_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
|
||||
if (method->create != NULL) {
|
||||
if (!method->create(bio)) {
|
||||
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio,
|
||||
&bio->ex_data);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_set);
|
||||
|
||||
int
|
||||
BIO_free(BIO *a)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (a == NULL)
|
||||
return (0);
|
||||
|
||||
if (CRYPTO_add(&a->references, -1, CRYPTO_LOCK_BIO) > 0)
|
||||
return (1);
|
||||
|
||||
if (a->callback != NULL || a->callback_ex != NULL) {
|
||||
if ((ret = (int)bio_call_callback(a, BIO_CB_FREE, NULL, 0, 0,
|
||||
0L, 1L, NULL)) <= 0)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, a, &a->ex_data);
|
||||
|
||||
if (a->method != NULL && a->method->destroy != NULL)
|
||||
a->method->destroy(a);
|
||||
free(a);
|
||||
return (1);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_free);
|
||||
|
||||
void
|
||||
BIO_vfree(BIO *a)
|
||||
{
|
||||
BIO_free(a);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_vfree);
|
||||
|
||||
int
|
||||
BIO_up_ref(BIO *bio)
|
||||
{
|
||||
int refs = CRYPTO_add(&bio->references, 1, CRYPTO_LOCK_BIO);
|
||||
return (refs > 1) ? 1 : 0;
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_up_ref);
|
||||
|
||||
void *
|
||||
BIO_get_data(BIO *a)
|
||||
{
|
||||
return (a->ptr);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_get_data);
|
||||
|
||||
void
|
||||
BIO_set_data(BIO *a, void *ptr)
|
||||
{
|
||||
a->ptr = ptr;
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_set_data);
|
||||
|
||||
int
|
||||
BIO_get_init(BIO *a)
|
||||
{
|
||||
return a->init;
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_get_init);
|
||||
|
||||
void
|
||||
BIO_set_init(BIO *a, int init)
|
||||
{
|
||||
a->init = init;
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_set_init);
|
||||
|
||||
int
|
||||
BIO_get_shutdown(BIO *a)
|
||||
{
|
||||
return (a->shutdown);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_get_shutdown);
|
||||
|
||||
void
|
||||
BIO_set_shutdown(BIO *a, int shut)
|
||||
{
|
||||
a->shutdown = shut;
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_set_shutdown);
|
||||
|
||||
void
|
||||
BIO_clear_flags(BIO *b, int flags)
|
||||
{
|
||||
b->flags &= ~flags;
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_clear_flags);
|
||||
|
||||
int
|
||||
BIO_test_flags(const BIO *b, int flags)
|
||||
{
|
||||
return (b->flags & flags);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_test_flags);
|
||||
|
||||
void
|
||||
BIO_set_flags(BIO *b, int flags)
|
||||
{
|
||||
b->flags |= flags;
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_set_flags);
|
||||
|
||||
BIO_callback_fn
|
||||
BIO_get_callback(const BIO *b)
|
||||
{
|
||||
return b->callback;
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_get_callback);
|
||||
|
||||
void
|
||||
BIO_set_callback(BIO *b, BIO_callback_fn cb)
|
||||
{
|
||||
b->callback = cb;
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_set_callback);
|
||||
|
||||
BIO_callback_fn_ex
|
||||
BIO_get_callback_ex(const BIO *b)
|
||||
{
|
||||
return b->callback_ex;
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_get_callback_ex);
|
||||
|
||||
void
|
||||
BIO_set_callback_ex(BIO *b, BIO_callback_fn_ex cb)
|
||||
{
|
||||
b->callback_ex = cb;
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_set_callback_ex);
|
||||
|
||||
void
|
||||
BIO_set_callback_arg(BIO *b, char *arg)
|
||||
{
|
||||
b->cb_arg = arg;
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_set_callback_arg);
|
||||
|
||||
char *
|
||||
BIO_get_callback_arg(const BIO *b)
|
||||
{
|
||||
return b->cb_arg;
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_get_callback_arg);
|
||||
|
||||
const char *
|
||||
BIO_method_name(const BIO *b)
|
||||
{
|
||||
return b->method->name;
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_method_name);
|
||||
|
||||
int
|
||||
BIO_method_type(const BIO *b)
|
||||
{
|
||||
return b->method->type;
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_method_type);
|
||||
|
||||
int
|
||||
BIO_read(BIO *b, void *out, int outl)
|
||||
{
|
||||
size_t readbytes = 0;
|
||||
int ret;
|
||||
|
||||
if (b == NULL) {
|
||||
BIOerror(ERR_R_PASSED_NULL_PARAMETER);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (outl <= 0)
|
||||
return (0);
|
||||
|
||||
if (out == NULL) {
|
||||
BIOerror(ERR_R_PASSED_NULL_PARAMETER);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (b->method == NULL || b->method->bread == NULL) {
|
||||
BIOerror(BIO_R_UNSUPPORTED_METHOD);
|
||||
return (-2);
|
||||
}
|
||||
|
||||
if (b->callback != NULL || b->callback_ex != NULL) {
|
||||
if ((ret = (int)bio_call_callback(b, BIO_CB_READ, out, outl, 0,
|
||||
0L, 1L, NULL)) <= 0)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
if (!b->init) {
|
||||
BIOerror(BIO_R_UNINITIALIZED);
|
||||
return (-2);
|
||||
}
|
||||
|
||||
if ((ret = b->method->bread(b, out, outl)) > 0)
|
||||
readbytes = (size_t)ret;
|
||||
|
||||
b->num_read += readbytes;
|
||||
|
||||
if (b->callback != NULL || b->callback_ex != NULL) {
|
||||
ret = (int)bio_call_callback(b, BIO_CB_READ | BIO_CB_RETURN,
|
||||
out, outl, 0, 0L, (ret > 0) ? 1 : ret, &readbytes);
|
||||
}
|
||||
|
||||
if (ret > 0) {
|
||||
if (readbytes > INT_MAX) {
|
||||
BIOerror(BIO_R_LENGTH_TOO_LONG);
|
||||
ret = -1;
|
||||
} else {
|
||||
ret = (int)readbytes;
|
||||
}
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_read);
|
||||
|
||||
int
|
||||
BIO_write(BIO *b, const void *in, int inl)
|
||||
{
|
||||
size_t writebytes = 0;
|
||||
int ret;
|
||||
|
||||
/* Not an error. Things like SMIME_text() assume that this succeeds. */
|
||||
if (b == NULL)
|
||||
return (0);
|
||||
|
||||
if (inl <= 0)
|
||||
return (0);
|
||||
|
||||
if (in == NULL) {
|
||||
BIOerror(ERR_R_PASSED_NULL_PARAMETER);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (b->method == NULL || b->method->bwrite == NULL) {
|
||||
BIOerror(BIO_R_UNSUPPORTED_METHOD);
|
||||
return (-2);
|
||||
}
|
||||
|
||||
if (b->callback != NULL || b->callback_ex != NULL) {
|
||||
if ((ret = (int)bio_call_callback(b, BIO_CB_WRITE, in, inl, 0,
|
||||
0L, 1L, NULL)) <= 0)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
if (!b->init) {
|
||||
BIOerror(BIO_R_UNINITIALIZED);
|
||||
return (-2);
|
||||
}
|
||||
|
||||
if ((ret = b->method->bwrite(b, in, inl)) > 0)
|
||||
writebytes = ret;
|
||||
|
||||
b->num_write += writebytes;
|
||||
|
||||
if (b->callback != NULL || b->callback_ex != NULL) {
|
||||
ret = (int)bio_call_callback(b, BIO_CB_WRITE | BIO_CB_RETURN,
|
||||
in, inl, 0, 0L, (ret > 0) ? 1 : ret, &writebytes);
|
||||
}
|
||||
|
||||
if (ret > 0) {
|
||||
if (writebytes > INT_MAX) {
|
||||
BIOerror(BIO_R_LENGTH_TOO_LONG);
|
||||
ret = -1;
|
||||
} else {
|
||||
ret = (int)writebytes;
|
||||
}
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_write);
|
||||
|
||||
int
|
||||
BIO_puts(BIO *b, const char *in)
|
||||
{
|
||||
size_t writebytes = 0;
|
||||
int ret;
|
||||
|
||||
if (b == NULL || b->method == NULL || b->method->bputs == NULL) {
|
||||
BIOerror(BIO_R_UNSUPPORTED_METHOD);
|
||||
return (-2);
|
||||
}
|
||||
|
||||
if (b->callback != NULL || b->callback_ex != NULL) {
|
||||
if ((ret = (int)bio_call_callback(b, BIO_CB_PUTS, in, 0, 0, 0L,
|
||||
1L, NULL)) <= 0)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
if (!b->init) {
|
||||
BIOerror(BIO_R_UNINITIALIZED);
|
||||
return (-2);
|
||||
}
|
||||
|
||||
if ((ret = b->method->bputs(b, in)) > 0)
|
||||
writebytes = ret;
|
||||
|
||||
b->num_write += writebytes;
|
||||
|
||||
if (b->callback != NULL || b->callback_ex != NULL) {
|
||||
ret = (int)bio_call_callback(b, BIO_CB_PUTS | BIO_CB_RETURN,
|
||||
in, 0, 0, 0L, (ret > 0) ? 1 : ret, &writebytes);
|
||||
}
|
||||
|
||||
if (ret > 0) {
|
||||
if (writebytes > INT_MAX) {
|
||||
BIOerror(BIO_R_LENGTH_TOO_LONG);
|
||||
ret = -1;
|
||||
} else {
|
||||
ret = (int)writebytes;
|
||||
}
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_puts);
|
||||
|
||||
int
|
||||
BIO_gets(BIO *b, char *in, int inl)
|
||||
{
|
||||
size_t readbytes = 0;
|
||||
int ret;
|
||||
|
||||
if (b == NULL || b->method == NULL || b->method->bgets == NULL) {
|
||||
BIOerror(BIO_R_UNSUPPORTED_METHOD);
|
||||
return (-2);
|
||||
}
|
||||
|
||||
if (b->callback != NULL || b->callback_ex != NULL) {
|
||||
if ((ret = (int)bio_call_callback(b, BIO_CB_GETS, in, inl, 0, 0L,
|
||||
1, NULL)) <= 0)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
if (!b->init) {
|
||||
BIOerror(BIO_R_UNINITIALIZED);
|
||||
return (-2);
|
||||
}
|
||||
|
||||
if ((ret = b->method->bgets(b, in, inl)) > 0)
|
||||
readbytes = ret;
|
||||
|
||||
if (b->callback != NULL || b->callback_ex != NULL) {
|
||||
ret = (int)bio_call_callback(b, BIO_CB_GETS | BIO_CB_RETURN, in,
|
||||
inl, 0, 0L, (ret > 0) ? 1 : ret, &readbytes);
|
||||
}
|
||||
|
||||
if (ret > 0) {
|
||||
if (readbytes > INT_MAX) {
|
||||
BIOerror(BIO_R_LENGTH_TOO_LONG);
|
||||
ret = -1;
|
||||
} else {
|
||||
ret = (int)readbytes;
|
||||
}
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_gets);
|
||||
|
||||
int
|
||||
BIO_indent(BIO *b, int indent, int max)
|
||||
{
|
||||
if (indent > max)
|
||||
indent = max;
|
||||
if (indent <= 0)
|
||||
return 1;
|
||||
if (BIO_printf(b, "%*s", indent, "") <= 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_indent);
|
||||
|
||||
long
|
||||
BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = iarg;
|
||||
return (BIO_ctrl(b, cmd, larg, (char *)&i));
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_int_ctrl);
|
||||
|
||||
char *
|
||||
BIO_ptr_ctrl(BIO *b, int cmd, long larg)
|
||||
{
|
||||
char *p = NULL;
|
||||
|
||||
if (BIO_ctrl(b, cmd, larg, (char *)&p) <= 0)
|
||||
return (NULL);
|
||||
else
|
||||
return (p);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_ptr_ctrl);
|
||||
|
||||
long
|
||||
BIO_ctrl(BIO *b, int cmd, long larg, void *parg)
|
||||
{
|
||||
long ret;
|
||||
|
||||
if (b == NULL)
|
||||
return (0);
|
||||
|
||||
if (b->method == NULL || b->method->ctrl == NULL) {
|
||||
BIOerror(BIO_R_UNSUPPORTED_METHOD);
|
||||
return (-2);
|
||||
}
|
||||
|
||||
if (b->callback != NULL || b->callback_ex != NULL) {
|
||||
if ((ret = bio_call_callback(b, BIO_CB_CTRL, parg, 0, cmd, larg,
|
||||
1L, NULL)) <= 0)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
ret = b->method->ctrl(b, cmd, larg, parg);
|
||||
|
||||
if (b->callback != NULL || b->callback_ex != NULL) {
|
||||
ret = bio_call_callback(b, BIO_CB_CTRL | BIO_CB_RETURN, parg, 0,
|
||||
cmd, larg, ret, NULL);
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_ctrl);
|
||||
|
||||
long
|
||||
BIO_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
|
||||
{
|
||||
long ret;
|
||||
|
||||
if (b == NULL)
|
||||
return (0);
|
||||
|
||||
if (b->method == NULL || b->method->callback_ctrl == NULL ||
|
||||
cmd != BIO_CTRL_SET_CALLBACK) {
|
||||
BIOerror(BIO_R_UNSUPPORTED_METHOD);
|
||||
return (-2);
|
||||
}
|
||||
|
||||
if (b->callback != NULL || b->callback_ex != NULL) {
|
||||
if ((ret = bio_call_callback(b, BIO_CB_CTRL, (void *)&fp, 0,
|
||||
cmd, 0, 1L, NULL)) <= 0)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
ret = b->method->callback_ctrl(b, cmd, fp);
|
||||
|
||||
if (b->callback != NULL || b->callback_ex != NULL) {
|
||||
ret = bio_call_callback(b, BIO_CB_CTRL | BIO_CB_RETURN,
|
||||
(void *)&fp, 0, cmd, 0, ret, NULL);
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_callback_ctrl);
|
||||
|
||||
/* It is unfortunate to duplicate in functions what the BIO_(w)pending macros
|
||||
* do; but those macros have inappropriate return type, and for interfacing
|
||||
* from other programming languages, C macros aren't much of a help anyway. */
|
||||
size_t
|
||||
BIO_ctrl_pending(BIO *bio)
|
||||
{
|
||||
return BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_ctrl_pending);
|
||||
|
||||
size_t
|
||||
BIO_ctrl_wpending(BIO *bio)
|
||||
{
|
||||
return BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_ctrl_wpending);
|
||||
|
||||
|
||||
/*
|
||||
* Append "bio" to the end of the chain containing "b":
|
||||
* Two chains "b -> lb" and "oldhead -> bio"
|
||||
* become two chains "b -> lb -> bio" and "oldhead".
|
||||
*/
|
||||
BIO *
|
||||
BIO_push(BIO *b, BIO *bio)
|
||||
{
|
||||
BIO *lb;
|
||||
|
||||
if (b == NULL)
|
||||
return (bio);
|
||||
lb = b;
|
||||
while (lb->next_bio != NULL)
|
||||
lb = lb->next_bio;
|
||||
lb->next_bio = bio;
|
||||
if (bio != NULL) {
|
||||
if (bio->prev_bio != NULL)
|
||||
bio->prev_bio->next_bio = NULL;
|
||||
bio->prev_bio = lb;
|
||||
}
|
||||
/* called to do internal processing */
|
||||
BIO_ctrl(b, BIO_CTRL_PUSH, 0, lb);
|
||||
return (b);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_push);
|
||||
|
||||
/* Remove the first and return the rest */
|
||||
BIO *
|
||||
BIO_pop(BIO *b)
|
||||
{
|
||||
BIO *ret;
|
||||
|
||||
if (b == NULL)
|
||||
return (NULL);
|
||||
ret = b->next_bio;
|
||||
|
||||
BIO_ctrl(b, BIO_CTRL_POP, 0, b);
|
||||
|
||||
if (b->prev_bio != NULL)
|
||||
b->prev_bio->next_bio = b->next_bio;
|
||||
if (b->next_bio != NULL)
|
||||
b->next_bio->prev_bio = b->prev_bio;
|
||||
|
||||
b->next_bio = NULL;
|
||||
b->prev_bio = NULL;
|
||||
return (ret);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_pop);
|
||||
|
||||
BIO *
|
||||
BIO_get_retry_BIO(BIO *bio, int *reason)
|
||||
{
|
||||
BIO *b, *last;
|
||||
|
||||
b = last = bio;
|
||||
for (;;) {
|
||||
if (!BIO_should_retry(b))
|
||||
break;
|
||||
last = b;
|
||||
b = b->next_bio;
|
||||
if (b == NULL)
|
||||
break;
|
||||
}
|
||||
if (reason != NULL)
|
||||
*reason = last->retry_reason;
|
||||
return (last);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_get_retry_BIO);
|
||||
|
||||
int
|
||||
BIO_get_retry_reason(BIO *bio)
|
||||
{
|
||||
return (bio->retry_reason);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_get_retry_reason);
|
||||
|
||||
void
|
||||
BIO_set_retry_reason(BIO *bio, int reason)
|
||||
{
|
||||
bio->retry_reason = reason;
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_set_retry_reason);
|
||||
|
||||
BIO *
|
||||
BIO_find_type(BIO *bio, int type)
|
||||
{
|
||||
int mt, mask;
|
||||
|
||||
if (!bio)
|
||||
return NULL;
|
||||
mask = type & 0xff;
|
||||
do {
|
||||
if (bio->method != NULL) {
|
||||
mt = bio->method->type;
|
||||
if (!mask) {
|
||||
if (mt & type)
|
||||
return (bio);
|
||||
} else if (mt == type)
|
||||
return (bio);
|
||||
}
|
||||
bio = bio->next_bio;
|
||||
} while (bio != NULL);
|
||||
return (NULL);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_find_type);
|
||||
|
||||
BIO *
|
||||
BIO_next(BIO *b)
|
||||
{
|
||||
if (!b)
|
||||
return NULL;
|
||||
return b->next_bio;
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_next);
|
||||
|
||||
/*
|
||||
* Two chains "bio -> oldtail" and "oldhead -> next" become
|
||||
* three chains "oldtail", "bio -> next", and "oldhead".
|
||||
*/
|
||||
void
|
||||
BIO_set_next(BIO *bio, BIO *next)
|
||||
{
|
||||
/* Cut off the tail of the chain containing bio after bio. */
|
||||
if (bio->next_bio != NULL)
|
||||
bio->next_bio->prev_bio = NULL;
|
||||
|
||||
/* Cut off the head of the chain containing next before next. */
|
||||
if (next != NULL && next->prev_bio != NULL)
|
||||
next->prev_bio->next_bio = NULL;
|
||||
|
||||
/* Append the chain starting at next to the chain ending at bio. */
|
||||
bio->next_bio = next;
|
||||
if (next != NULL)
|
||||
next->prev_bio = bio;
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_set_next);
|
||||
|
||||
void
|
||||
BIO_free_all(BIO *bio)
|
||||
{
|
||||
BIO *b;
|
||||
int ref;
|
||||
|
||||
while (bio != NULL) {
|
||||
b = bio;
|
||||
ref = b->references;
|
||||
bio = bio->next_bio;
|
||||
BIO_free(b);
|
||||
/* Since ref count > 1, don't free anyone else. */
|
||||
if (ref > 1)
|
||||
break;
|
||||
}
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_free_all);
|
||||
|
||||
BIO *
|
||||
BIO_dup_chain(BIO *in)
|
||||
{
|
||||
BIO *new_chain = NULL, *new_bio = NULL, *tail = NULL;
|
||||
BIO *bio;
|
||||
|
||||
for (bio = in; bio != NULL; bio = bio->next_bio) {
|
||||
if ((new_bio = BIO_new(bio->method)) == NULL)
|
||||
goto err;
|
||||
new_bio->callback = bio->callback;
|
||||
new_bio->callback_ex = bio->callback_ex;
|
||||
new_bio->cb_arg = bio->cb_arg;
|
||||
new_bio->init = bio->init;
|
||||
new_bio->shutdown = bio->shutdown;
|
||||
new_bio->flags = bio->flags;
|
||||
new_bio->num = bio->num;
|
||||
|
||||
if (!BIO_dup_state(bio, new_bio))
|
||||
goto err;
|
||||
|
||||
if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_BIO,
|
||||
&new_bio->ex_data, &bio->ex_data))
|
||||
goto err;
|
||||
|
||||
if (BIO_push(tail, new_bio) == NULL)
|
||||
goto err;
|
||||
|
||||
tail = new_bio;
|
||||
if (new_chain == NULL)
|
||||
new_chain = new_bio;
|
||||
}
|
||||
|
||||
return new_chain;
|
||||
|
||||
err:
|
||||
BIO_free(new_bio);
|
||||
BIO_free_all(new_chain);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_dup_chain);
|
||||
|
||||
void
|
||||
BIO_copy_next_retry(BIO *b)
|
||||
{
|
||||
BIO_set_flags(b, BIO_get_retry_flags(b->next_bio));
|
||||
b->retry_reason = b->next_bio->retry_reason;
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_copy_next_retry);
|
||||
|
||||
int
|
||||
BIO_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
|
||||
CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
|
||||
{
|
||||
return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_BIO, argl, argp,
|
||||
new_func, dup_func, free_func);
|
||||
}
|
||||
|
||||
int
|
||||
BIO_set_ex_data(BIO *bio, int idx, void *data)
|
||||
{
|
||||
return (CRYPTO_set_ex_data(&(bio->ex_data), idx, data));
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_set_ex_data);
|
||||
|
||||
void *
|
||||
BIO_get_ex_data(BIO *bio, int idx)
|
||||
{
|
||||
return (CRYPTO_get_ex_data(&(bio->ex_data), idx));
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_get_ex_data);
|
||||
|
||||
unsigned long
|
||||
BIO_number_read(BIO *bio)
|
||||
{
|
||||
if (bio)
|
||||
return bio->num_read;
|
||||
return 0;
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_number_read);
|
||||
|
||||
unsigned long
|
||||
BIO_number_written(BIO *bio)
|
||||
{
|
||||
if (bio)
|
||||
return bio->num_write;
|
||||
return 0;
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_number_written);
|
123
crypto/bio/bio_local.h
Normal file
123
crypto/bio/bio_local.h
Normal file
@@ -0,0 +1,123 @@
|
||||
/* $OpenBSD: bio_local.h,v 1.5 2022/12/02 19:44:04 tb Exp $ */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#ifndef HEADER_BIO_LOCAL_H
|
||||
#define HEADER_BIO_LOCAL_H
|
||||
|
||||
__BEGIN_HIDDEN_DECLS
|
||||
|
||||
struct bio_method_st {
|
||||
int type;
|
||||
const char *name;
|
||||
int (*bwrite)(BIO *, const char *, int);
|
||||
int (*bread)(BIO *, char *, int);
|
||||
int (*bputs)(BIO *, const char *);
|
||||
int (*bgets)(BIO *, char *, int);
|
||||
long (*ctrl)(BIO *, int, long, void *);
|
||||
int (*create)(BIO *);
|
||||
int (*destroy)(BIO *);
|
||||
long (*callback_ctrl)(BIO *, int, BIO_info_cb *);
|
||||
} /* BIO_METHOD */;
|
||||
|
||||
struct bio_st {
|
||||
const BIO_METHOD *method;
|
||||
BIO_callback_fn callback;
|
||||
BIO_callback_fn_ex callback_ex;
|
||||
char *cb_arg; /* first argument for the callback */
|
||||
|
||||
int init;
|
||||
int shutdown;
|
||||
int flags; /* extra storage */
|
||||
int retry_reason;
|
||||
int num;
|
||||
void *ptr;
|
||||
struct bio_st *next_bio; /* used by filter BIOs */
|
||||
struct bio_st *prev_bio; /* used by filter BIOs */
|
||||
int references;
|
||||
unsigned long num_read;
|
||||
unsigned long num_write;
|
||||
|
||||
CRYPTO_EX_DATA ex_data;
|
||||
} /* BIO */;
|
||||
|
||||
typedef struct bio_f_buffer_ctx_struct {
|
||||
/* Buffers are setup like this:
|
||||
*
|
||||
* <---------------------- size ----------------------->
|
||||
* +---------------------------------------------------+
|
||||
* | consumed | remaining | free space |
|
||||
* +---------------------------------------------------+
|
||||
* <-- off --><------- len ------->
|
||||
*/
|
||||
|
||||
/* BIO *bio; */ /* this is now in the BIO struct */
|
||||
int ibuf_size; /* how big is the input buffer */
|
||||
int obuf_size; /* how big is the output buffer */
|
||||
|
||||
char *ibuf; /* the char array */
|
||||
int ibuf_len; /* how many bytes are in it */
|
||||
int ibuf_off; /* write/read offset */
|
||||
|
||||
char *obuf; /* the char array */
|
||||
int obuf_len; /* how many bytes are in it */
|
||||
int obuf_off; /* write/read offset */
|
||||
} BIO_F_BUFFER_CTX;
|
||||
|
||||
__END_HIDDEN_DECLS
|
||||
|
||||
#endif /* !HEADER_BIO_LOCAL_H */
|
165
crypto/bio/bio_meth.c
Normal file
165
crypto/bio/bio_meth.c
Normal file
@@ -0,0 +1,165 @@
|
||||
/* $OpenBSD: bio_meth.c,v 1.9 2023/07/05 21:23:37 beck Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2018 Theo Buehler <tb@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <openssl/bio.h>
|
||||
|
||||
#include "bio_local.h"
|
||||
|
||||
BIO_METHOD *
|
||||
BIO_meth_new(int type, const char *name)
|
||||
{
|
||||
BIO_METHOD *biom;
|
||||
|
||||
if ((biom = calloc(1, sizeof(*biom))) == NULL)
|
||||
return NULL;
|
||||
|
||||
biom->type = type;
|
||||
biom->name = name;
|
||||
|
||||
return biom;
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_meth_new);
|
||||
|
||||
void
|
||||
BIO_meth_free(BIO_METHOD *biom)
|
||||
{
|
||||
free(biom);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_meth_free);
|
||||
|
||||
int
|
||||
(*BIO_meth_get_write(const BIO_METHOD *biom))(BIO *, const char *, int)
|
||||
{
|
||||
return biom->bwrite;
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_meth_get_write);
|
||||
|
||||
int
|
||||
BIO_meth_set_write(BIO_METHOD *biom, int (*write)(BIO *, const char *, int))
|
||||
{
|
||||
biom->bwrite = write;
|
||||
return 1;
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_meth_set_write);
|
||||
|
||||
int
|
||||
(*BIO_meth_get_read(const BIO_METHOD *biom))(BIO *, char *, int)
|
||||
{
|
||||
return biom->bread;
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_meth_get_read);
|
||||
|
||||
int
|
||||
BIO_meth_set_read(BIO_METHOD *biom, int (*read)(BIO *, char *, int))
|
||||
{
|
||||
biom->bread = read;
|
||||
return 1;
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_meth_set_read);
|
||||
|
||||
int
|
||||
(*BIO_meth_get_puts(const BIO_METHOD *biom))(BIO *, const char *)
|
||||
{
|
||||
return biom->bputs;
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_meth_get_puts);
|
||||
|
||||
int
|
||||
BIO_meth_set_puts(BIO_METHOD *biom, int (*puts)(BIO *, const char *))
|
||||
{
|
||||
biom->bputs = puts;
|
||||
return 1;
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_meth_set_puts);
|
||||
|
||||
int
|
||||
(*BIO_meth_get_gets(const BIO_METHOD *biom))(BIO *, char *, int)
|
||||
{
|
||||
return biom->bgets;
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_meth_get_gets);
|
||||
|
||||
int
|
||||
BIO_meth_set_gets(BIO_METHOD *biom, int (*gets)(BIO *, char *, int))
|
||||
{
|
||||
biom->bgets = gets;
|
||||
return 1;
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_meth_set_gets);
|
||||
|
||||
long
|
||||
(*BIO_meth_get_ctrl(const BIO_METHOD *biom))(BIO *, int, long, void *)
|
||||
{
|
||||
return biom->ctrl;
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_meth_get_ctrl);
|
||||
|
||||
int
|
||||
BIO_meth_set_ctrl(BIO_METHOD *biom, long (*ctrl)(BIO *, int, long, void *))
|
||||
{
|
||||
biom->ctrl = ctrl;
|
||||
return 1;
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_meth_set_ctrl);
|
||||
|
||||
int
|
||||
(*BIO_meth_get_create(const BIO_METHOD *biom))(BIO *)
|
||||
{
|
||||
return biom->create;
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_meth_get_create);
|
||||
|
||||
int
|
||||
BIO_meth_set_create(BIO_METHOD *biom, int (*create)(BIO *))
|
||||
{
|
||||
biom->create = create;
|
||||
return 1;
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_meth_set_create);
|
||||
|
||||
int
|
||||
(*BIO_meth_get_destroy(const BIO_METHOD *biom))(BIO *)
|
||||
{
|
||||
return biom->destroy;
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_meth_get_destroy);
|
||||
|
||||
int
|
||||
BIO_meth_set_destroy(BIO_METHOD *biom, int (*destroy)(BIO *))
|
||||
{
|
||||
biom->destroy = destroy;
|
||||
return 1;
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_meth_set_destroy);
|
||||
|
||||
long
|
||||
(*BIO_meth_get_callback_ctrl(const BIO_METHOD *biom))(BIO *, int, BIO_info_cb *)
|
||||
{
|
||||
return biom->callback_ctrl;
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_meth_get_callback_ctrl);
|
||||
|
||||
int
|
||||
BIO_meth_set_callback_ctrl(BIO_METHOD *biom,
|
||||
long (*callback_ctrl)(BIO *, int, BIO_info_cb *))
|
||||
{
|
||||
biom->callback_ctrl = callback_ctrl;
|
||||
return 1;
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_meth_set_callback_ctrl);
|
456
crypto/bio/bss_acpt.c
Normal file
456
crypto/bio/bss_acpt.c
Normal file
@@ -0,0 +1,456 @@
|
||||
/* $OpenBSD: bss_acpt.c,v 1.31 2023/07/05 21:23:37 beck Exp $ */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/buffer.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "bio_local.h"
|
||||
|
||||
#define SOCKET_PROTOCOL IPPROTO_TCP
|
||||
|
||||
typedef struct bio_accept_st {
|
||||
int state;
|
||||
char *param_addr;
|
||||
|
||||
int accept_sock;
|
||||
int accept_nbio;
|
||||
|
||||
char *addr;
|
||||
int nbio;
|
||||
/* If 0, it means normal, if 1, do a connect on bind failure,
|
||||
* and if there is no-one listening, bind with SO_REUSEADDR.
|
||||
* If 2, always use SO_REUSEADDR. */
|
||||
int bind_mode;
|
||||
BIO *bio_chain;
|
||||
} BIO_ACCEPT;
|
||||
|
||||
static int acpt_write(BIO *h, const char *buf, int num);
|
||||
static int acpt_read(BIO *h, char *buf, int size);
|
||||
static int acpt_puts(BIO *h, const char *str);
|
||||
static long acpt_ctrl(BIO *h, int cmd, long arg1, void *arg2);
|
||||
static int acpt_new(BIO *h);
|
||||
static int acpt_free(BIO *data);
|
||||
static int acpt_state(BIO *b, BIO_ACCEPT *c);
|
||||
static void acpt_close_socket(BIO *data);
|
||||
static BIO_ACCEPT *BIO_ACCEPT_new(void );
|
||||
static void BIO_ACCEPT_free(BIO_ACCEPT *a);
|
||||
|
||||
#define ACPT_S_BEFORE 1
|
||||
#define ACPT_S_GET_ACCEPT_SOCKET 2
|
||||
#define ACPT_S_OK 3
|
||||
|
||||
static const BIO_METHOD methods_acceptp = {
|
||||
.type = BIO_TYPE_ACCEPT,
|
||||
.name = "socket accept",
|
||||
.bwrite = acpt_write,
|
||||
.bread = acpt_read,
|
||||
.bputs = acpt_puts,
|
||||
.ctrl = acpt_ctrl,
|
||||
.create = acpt_new,
|
||||
.destroy = acpt_free
|
||||
};
|
||||
|
||||
const BIO_METHOD *
|
||||
BIO_s_accept(void)
|
||||
{
|
||||
return (&methods_acceptp);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_s_accept);
|
||||
|
||||
static int
|
||||
acpt_new(BIO *bi)
|
||||
{
|
||||
BIO_ACCEPT *ba;
|
||||
|
||||
bi->init = 0;
|
||||
bi->num = -1;
|
||||
bi->flags = 0;
|
||||
if ((ba = BIO_ACCEPT_new()) == NULL)
|
||||
return (0);
|
||||
bi->ptr = (char *)ba;
|
||||
ba->state = ACPT_S_BEFORE;
|
||||
bi->shutdown = 1;
|
||||
return (1);
|
||||
}
|
||||
|
||||
static BIO_ACCEPT *
|
||||
BIO_ACCEPT_new(void)
|
||||
{
|
||||
BIO_ACCEPT *ret;
|
||||
|
||||
if ((ret = calloc(1, sizeof(BIO_ACCEPT))) == NULL)
|
||||
return (NULL);
|
||||
ret->accept_sock = -1;
|
||||
ret->bind_mode = BIO_BIND_NORMAL;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static void
|
||||
BIO_ACCEPT_free(BIO_ACCEPT *a)
|
||||
{
|
||||
if (a == NULL)
|
||||
return;
|
||||
|
||||
free(a->param_addr);
|
||||
free(a->addr);
|
||||
BIO_free(a->bio_chain);
|
||||
free(a);
|
||||
}
|
||||
|
||||
static void
|
||||
acpt_close_socket(BIO *bio)
|
||||
{
|
||||
BIO_ACCEPT *c;
|
||||
|
||||
c = (BIO_ACCEPT *)bio->ptr;
|
||||
if (c->accept_sock != -1) {
|
||||
shutdown(c->accept_sock, SHUT_RDWR);
|
||||
close(c->accept_sock);
|
||||
c->accept_sock = -1;
|
||||
bio->num = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
acpt_free(BIO *a)
|
||||
{
|
||||
BIO_ACCEPT *data;
|
||||
|
||||
if (a == NULL)
|
||||
return (0);
|
||||
data = (BIO_ACCEPT *)a->ptr;
|
||||
|
||||
if (a->shutdown) {
|
||||
acpt_close_socket(a);
|
||||
BIO_ACCEPT_free(data);
|
||||
a->ptr = NULL;
|
||||
a->flags = 0;
|
||||
a->init = 0;
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
acpt_state(BIO *b, BIO_ACCEPT *c)
|
||||
{
|
||||
BIO *bio = NULL, *dbio;
|
||||
int s = -1;
|
||||
int i;
|
||||
|
||||
again:
|
||||
switch (c->state) {
|
||||
case ACPT_S_BEFORE:
|
||||
if (c->param_addr == NULL) {
|
||||
BIOerror(BIO_R_NO_ACCEPT_PORT_SPECIFIED);
|
||||
return (-1);
|
||||
}
|
||||
s = BIO_get_accept_socket(c->param_addr, c->bind_mode);
|
||||
if (s == -1)
|
||||
return (-1);
|
||||
|
||||
if (c->accept_nbio) {
|
||||
if (!BIO_socket_nbio(s, 1)) {
|
||||
close(s);
|
||||
BIOerror(BIO_R_ERROR_SETTING_NBIO_ON_ACCEPT_SOCKET);
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
c->accept_sock = s;
|
||||
b->num = s;
|
||||
c->state = ACPT_S_GET_ACCEPT_SOCKET;
|
||||
return (1);
|
||||
/* break; */
|
||||
case ACPT_S_GET_ACCEPT_SOCKET:
|
||||
if (b->next_bio != NULL) {
|
||||
c->state = ACPT_S_OK;
|
||||
goto again;
|
||||
}
|
||||
BIO_clear_retry_flags(b);
|
||||
b->retry_reason = 0;
|
||||
i = BIO_accept(c->accept_sock, &(c->addr));
|
||||
|
||||
/* -2 return means we should retry */
|
||||
if (i == -2) {
|
||||
BIO_set_retry_special(b);
|
||||
b->retry_reason = BIO_RR_ACCEPT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (i < 0)
|
||||
return (i);
|
||||
|
||||
bio = BIO_new_socket(i, BIO_CLOSE);
|
||||
if (bio == NULL)
|
||||
goto err;
|
||||
|
||||
BIO_set_callback(bio, BIO_get_callback(b));
|
||||
BIO_set_callback_arg(bio, BIO_get_callback_arg(b));
|
||||
|
||||
if (c->nbio) {
|
||||
if (!BIO_socket_nbio(i, 1)) {
|
||||
BIOerror(BIO_R_ERROR_SETTING_NBIO_ON_ACCEPTED_SOCKET);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the accept BIO has an bio_chain, we dup it and
|
||||
* put the new socket at the end. */
|
||||
if (c->bio_chain != NULL) {
|
||||
if ((dbio = BIO_dup_chain(c->bio_chain)) == NULL)
|
||||
goto err;
|
||||
if (!BIO_push(dbio, bio)) goto err;
|
||||
bio = dbio;
|
||||
}
|
||||
if (BIO_push(b, bio)
|
||||
== NULL) goto err;
|
||||
|
||||
c->state = ACPT_S_OK;
|
||||
return (1);
|
||||
|
||||
err:
|
||||
if (bio != NULL)
|
||||
BIO_free(bio);
|
||||
return (0);
|
||||
/* break; */
|
||||
case ACPT_S_OK:
|
||||
if (b->next_bio == NULL) {
|
||||
c->state = ACPT_S_GET_ACCEPT_SOCKET;
|
||||
goto again;
|
||||
}
|
||||
return (1);
|
||||
/* break; */
|
||||
default:
|
||||
return (0);
|
||||
/* break; */
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
acpt_read(BIO *b, char *out, int outl)
|
||||
{
|
||||
int ret = 0;
|
||||
BIO_ACCEPT *data;
|
||||
|
||||
BIO_clear_retry_flags(b);
|
||||
data = (BIO_ACCEPT *)b->ptr;
|
||||
|
||||
while (b->next_bio == NULL) {
|
||||
ret = acpt_state(b, data);
|
||||
if (ret <= 0)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
ret = BIO_read(b->next_bio, out, outl);
|
||||
BIO_copy_next_retry(b);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
acpt_write(BIO *b, const char *in, int inl)
|
||||
{
|
||||
int ret;
|
||||
BIO_ACCEPT *data;
|
||||
|
||||
BIO_clear_retry_flags(b);
|
||||
data = (BIO_ACCEPT *)b->ptr;
|
||||
|
||||
while (b->next_bio == NULL) {
|
||||
ret = acpt_state(b, data);
|
||||
if (ret <= 0)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
ret = BIO_write(b->next_bio, in, inl);
|
||||
BIO_copy_next_retry(b);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static long
|
||||
acpt_ctrl(BIO *b, int cmd, long num, void *ptr)
|
||||
{
|
||||
int *ip;
|
||||
long ret = 1;
|
||||
BIO_ACCEPT *data;
|
||||
char **pp;
|
||||
|
||||
data = (BIO_ACCEPT *)b->ptr;
|
||||
|
||||
switch (cmd) {
|
||||
case BIO_CTRL_RESET:
|
||||
ret = 0;
|
||||
data->state = ACPT_S_BEFORE;
|
||||
acpt_close_socket(b);
|
||||
b->flags = 0;
|
||||
break;
|
||||
case BIO_C_DO_STATE_MACHINE:
|
||||
/* use this one to start the connection */
|
||||
ret = (long)acpt_state(b, data);
|
||||
break;
|
||||
case BIO_C_SET_ACCEPT:
|
||||
if (ptr != NULL) {
|
||||
if (num == 0) {
|
||||
b->init = 1;
|
||||
free(data->param_addr);
|
||||
data->param_addr = strdup(ptr);
|
||||
} else if (num == 1) {
|
||||
data->accept_nbio = (ptr != NULL);
|
||||
} else if (num == 2) {
|
||||
BIO_free(data->bio_chain);
|
||||
data->bio_chain = (BIO *)ptr;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BIO_C_SET_NBIO:
|
||||
data->nbio = (int)num;
|
||||
break;
|
||||
case BIO_C_SET_FD:
|
||||
b->init = 1;
|
||||
b->num= *((int *)ptr);
|
||||
data->accept_sock = b->num;
|
||||
data->state = ACPT_S_GET_ACCEPT_SOCKET;
|
||||
b->shutdown = (int)num;
|
||||
b->init = 1;
|
||||
break;
|
||||
case BIO_C_GET_FD:
|
||||
if (b->init) {
|
||||
ip = (int *)ptr;
|
||||
if (ip != NULL)
|
||||
*ip = data->accept_sock;
|
||||
ret = data->accept_sock;
|
||||
} else
|
||||
ret = -1;
|
||||
break;
|
||||
case BIO_C_GET_ACCEPT:
|
||||
if (b->init) {
|
||||
if (ptr != NULL) {
|
||||
pp = (char **)ptr;
|
||||
*pp = data->param_addr;
|
||||
} else
|
||||
ret = -1;
|
||||
} else
|
||||
ret = -1;
|
||||
break;
|
||||
case BIO_CTRL_GET_CLOSE:
|
||||
ret = b->shutdown;
|
||||
break;
|
||||
case BIO_CTRL_SET_CLOSE:
|
||||
b->shutdown = (int)num;
|
||||
break;
|
||||
case BIO_CTRL_PENDING:
|
||||
case BIO_CTRL_WPENDING:
|
||||
ret = 0;
|
||||
break;
|
||||
case BIO_CTRL_FLUSH:
|
||||
break;
|
||||
case BIO_C_SET_BIND_MODE:
|
||||
data->bind_mode = (int)num;
|
||||
break;
|
||||
case BIO_C_GET_BIND_MODE:
|
||||
ret = (long)data->bind_mode;
|
||||
break;
|
||||
case BIO_CTRL_DUP:
|
||||
/* dbio=(BIO *)ptr;
|
||||
if (data->param_port) EAY EAY
|
||||
BIO_set_port(dbio,data->param_port);
|
||||
if (data->param_hostname)
|
||||
BIO_set_hostname(dbio,data->param_hostname);
|
||||
BIO_set_nbio(dbio,data->nbio);
|
||||
*/
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
acpt_puts(BIO *bp, const char *str)
|
||||
{
|
||||
int n, ret;
|
||||
|
||||
n = strlen(str);
|
||||
ret = acpt_write(bp, str, n);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
BIO *
|
||||
BIO_new_accept(const char *str)
|
||||
{
|
||||
BIO *ret;
|
||||
|
||||
ret = BIO_new(BIO_s_accept());
|
||||
if (ret == NULL)
|
||||
return (NULL);
|
||||
if (BIO_set_accept_port(ret, str))
|
||||
return (ret);
|
||||
else {
|
||||
BIO_free(ret);
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_new_accept);
|
640
crypto/bio/bss_bio.c
Normal file
640
crypto/bio/bss_bio.c
Normal file
@@ -0,0 +1,640 @@
|
||||
/* $OpenBSD: bss_bio.c,v 1.28 2023/07/28 10:13:50 tb Exp $ */
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@openssl.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
/* Special method for a BIO where the other endpoint is also a BIO
|
||||
* of this kind, handled by the same thread (i.e. the "peer" is actually
|
||||
* ourselves, wearing a different hat).
|
||||
* Such "BIO pairs" are mainly for using the SSL library with I/O interfaces
|
||||
* for which no specific BIO method is available.
|
||||
* See ssl/ssltest.c for some hints on how this can be used. */
|
||||
|
||||
/* BIO_DEBUG implies BIO_PAIR_DEBUG */
|
||||
#ifdef BIO_DEBUG
|
||||
# ifndef BIO_PAIR_DEBUG
|
||||
# define BIO_PAIR_DEBUG
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* disable assert() unless BIO_PAIR_DEBUG has been defined */
|
||||
#ifndef BIO_PAIR_DEBUG
|
||||
# ifndef NDEBUG
|
||||
# define NDEBUG
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/crypto.h>
|
||||
|
||||
#include "bio_local.h"
|
||||
|
||||
static int bio_new(BIO *bio);
|
||||
static int bio_free(BIO *bio);
|
||||
static int bio_read(BIO *bio, char *buf, int size);
|
||||
static int bio_write(BIO *bio, const char *buf, int num);
|
||||
static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr);
|
||||
static int bio_puts(BIO *bio, const char *str);
|
||||
|
||||
static int bio_make_pair(BIO *bio1, BIO *bio2);
|
||||
static void bio_destroy_pair(BIO *bio);
|
||||
|
||||
static const BIO_METHOD methods_biop = {
|
||||
.type = BIO_TYPE_BIO,
|
||||
.name = "BIO pair",
|
||||
.bwrite = bio_write,
|
||||
.bread = bio_read,
|
||||
.bputs = bio_puts,
|
||||
.ctrl = bio_ctrl,
|
||||
.create = bio_new,
|
||||
.destroy = bio_free
|
||||
};
|
||||
|
||||
const BIO_METHOD *
|
||||
BIO_s_bio(void)
|
||||
{
|
||||
return &methods_biop;
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_s_bio);
|
||||
|
||||
struct bio_bio_st {
|
||||
BIO *peer; /* NULL if buf == NULL.
|
||||
* If peer != NULL, then peer->ptr is also a bio_bio_st,
|
||||
* and its "peer" member points back to us.
|
||||
* peer != NULL iff init != 0 in the BIO. */
|
||||
|
||||
/* This is for what we write (i.e. reading uses peer's struct): */
|
||||
int closed; /* valid iff peer != NULL */
|
||||
size_t len; /* valid iff buf != NULL; 0 if peer == NULL */
|
||||
size_t offset; /* valid iff buf != NULL; 0 if len == 0 */
|
||||
size_t size;
|
||||
char *buf; /* "size" elements (if != NULL) */
|
||||
|
||||
size_t request; /* valid iff peer != NULL; 0 if len != 0,
|
||||
* otherwise set by peer to number of bytes
|
||||
* it (unsuccessfully) tried to read,
|
||||
* never more than buffer space (size-len) warrants. */
|
||||
};
|
||||
|
||||
static int
|
||||
bio_new(BIO *bio)
|
||||
{
|
||||
struct bio_bio_st *b;
|
||||
|
||||
b = malloc(sizeof *b);
|
||||
if (b == NULL)
|
||||
return 0;
|
||||
|
||||
b->peer = NULL;
|
||||
b->size = 17 * 1024; /* enough for one TLS record (just a default) */
|
||||
b->buf = NULL;
|
||||
|
||||
bio->ptr = b;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
bio_free(BIO *bio)
|
||||
{
|
||||
struct bio_bio_st *b;
|
||||
|
||||
if (bio == NULL)
|
||||
return 0;
|
||||
b = bio->ptr;
|
||||
|
||||
assert(b != NULL);
|
||||
|
||||
if (b->peer)
|
||||
bio_destroy_pair(bio);
|
||||
|
||||
free(b->buf);
|
||||
free(b);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int
|
||||
bio_read(BIO *bio, char *buf, int size_)
|
||||
{
|
||||
size_t size = size_;
|
||||
size_t rest;
|
||||
struct bio_bio_st *b, *peer_b;
|
||||
|
||||
BIO_clear_retry_flags(bio);
|
||||
|
||||
if (!bio->init)
|
||||
return 0;
|
||||
|
||||
b = bio->ptr;
|
||||
assert(b != NULL);
|
||||
assert(b->peer != NULL);
|
||||
peer_b = b->peer->ptr;
|
||||
assert(peer_b != NULL);
|
||||
assert(peer_b->buf != NULL);
|
||||
|
||||
peer_b->request = 0; /* will be set in "retry_read" situation */
|
||||
|
||||
if (buf == NULL || size == 0)
|
||||
return 0;
|
||||
|
||||
if (peer_b->len == 0) {
|
||||
if (peer_b->closed)
|
||||
return 0; /* writer has closed, and no data is left */
|
||||
else {
|
||||
BIO_set_retry_read(bio); /* buffer is empty */
|
||||
if (size <= peer_b->size)
|
||||
peer_b->request = size;
|
||||
else
|
||||
/* don't ask for more than the peer can
|
||||
* deliver in one write */
|
||||
peer_b->request = peer_b->size;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* we can read */
|
||||
if (peer_b->len < size)
|
||||
size = peer_b->len;
|
||||
|
||||
/* now read "size" bytes */
|
||||
|
||||
rest = size;
|
||||
|
||||
assert(rest > 0);
|
||||
do /* one or two iterations */
|
||||
{
|
||||
size_t chunk;
|
||||
|
||||
assert(rest <= peer_b->len);
|
||||
if (peer_b->offset + rest <= peer_b->size)
|
||||
chunk = rest;
|
||||
else
|
||||
/* wrap around ring buffer */
|
||||
chunk = peer_b->size - peer_b->offset;
|
||||
assert(peer_b->offset + chunk <= peer_b->size);
|
||||
|
||||
memcpy(buf, peer_b->buf + peer_b->offset, chunk);
|
||||
|
||||
peer_b->len -= chunk;
|
||||
if (peer_b->len) {
|
||||
peer_b->offset += chunk;
|
||||
assert(peer_b->offset <= peer_b->size);
|
||||
if (peer_b->offset == peer_b->size)
|
||||
peer_b->offset = 0;
|
||||
buf += chunk;
|
||||
} else {
|
||||
/* buffer now empty, no need to advance "buf" */
|
||||
assert(chunk == rest);
|
||||
peer_b->offset = 0;
|
||||
}
|
||||
rest -= chunk;
|
||||
} while (rest);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static int
|
||||
bio_write(BIO *bio, const char *buf, int num_)
|
||||
{
|
||||
size_t num = num_;
|
||||
size_t rest;
|
||||
struct bio_bio_st *b;
|
||||
|
||||
BIO_clear_retry_flags(bio);
|
||||
|
||||
if (!bio->init || buf == NULL || num == 0)
|
||||
return 0;
|
||||
|
||||
b = bio->ptr;
|
||||
|
||||
assert(b != NULL);
|
||||
assert(b->peer != NULL);
|
||||
assert(b->buf != NULL);
|
||||
|
||||
b->request = 0;
|
||||
if (b->closed) {
|
||||
/* we already closed */
|
||||
BIOerror(BIO_R_BROKEN_PIPE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
assert(b->len <= b->size);
|
||||
|
||||
if (b->len == b->size) {
|
||||
BIO_set_retry_write(bio); /* buffer is full */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* we can write */
|
||||
if (num > b->size - b->len)
|
||||
num = b->size - b->len;
|
||||
|
||||
/* now write "num" bytes */
|
||||
|
||||
rest = num;
|
||||
|
||||
assert(rest > 0);
|
||||
do /* one or two iterations */
|
||||
{
|
||||
size_t write_offset;
|
||||
size_t chunk;
|
||||
|
||||
assert(b->len + rest <= b->size);
|
||||
|
||||
write_offset = b->offset + b->len;
|
||||
if (write_offset >= b->size)
|
||||
write_offset -= b->size;
|
||||
/* b->buf[write_offset] is the first byte we can write to. */
|
||||
|
||||
if (write_offset + rest <= b->size)
|
||||
chunk = rest;
|
||||
else
|
||||
/* wrap around ring buffer */
|
||||
chunk = b->size - write_offset;
|
||||
|
||||
memcpy(b->buf + write_offset, buf, chunk);
|
||||
|
||||
b->len += chunk;
|
||||
|
||||
assert(b->len <= b->size);
|
||||
|
||||
rest -= chunk;
|
||||
buf += chunk;
|
||||
} while (rest);
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
static long
|
||||
bio_ctrl(BIO *bio, int cmd, long num, void *ptr)
|
||||
{
|
||||
long ret;
|
||||
struct bio_bio_st *b = bio->ptr;
|
||||
|
||||
assert(b != NULL);
|
||||
|
||||
switch (cmd) {
|
||||
/* specific CTRL codes */
|
||||
|
||||
case BIO_C_SET_WRITE_BUF_SIZE:
|
||||
if (b->peer) {
|
||||
BIOerror(BIO_R_IN_USE);
|
||||
ret = 0;
|
||||
} else if (num == 0) {
|
||||
BIOerror(BIO_R_INVALID_ARGUMENT);
|
||||
ret = 0;
|
||||
} else {
|
||||
size_t new_size = num;
|
||||
|
||||
if (b->size != new_size) {
|
||||
free(b->buf);
|
||||
b->buf = NULL;
|
||||
b->size = new_size;
|
||||
}
|
||||
ret = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case BIO_C_GET_WRITE_BUF_SIZE:
|
||||
ret = (long) b->size;
|
||||
break;
|
||||
|
||||
case BIO_C_MAKE_BIO_PAIR:
|
||||
{
|
||||
BIO *other_bio = ptr;
|
||||
|
||||
if (bio_make_pair(bio, other_bio))
|
||||
ret = 1;
|
||||
else
|
||||
ret = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case BIO_C_DESTROY_BIO_PAIR:
|
||||
/* Affects both BIOs in the pair -- call just once!
|
||||
* Or let BIO_free(bio1); BIO_free(bio2); do the job. */
|
||||
bio_destroy_pair(bio);
|
||||
ret = 1;
|
||||
break;
|
||||
|
||||
case BIO_C_GET_WRITE_GUARANTEE:
|
||||
/* How many bytes can the caller feed to the next write
|
||||
* without having to keep any? */
|
||||
if (b->peer == NULL || b->closed)
|
||||
ret = 0;
|
||||
else
|
||||
ret = (long) b->size - b->len;
|
||||
break;
|
||||
|
||||
case BIO_C_GET_READ_REQUEST:
|
||||
/* If the peer unsuccessfully tried to read, how many bytes
|
||||
* were requested? (As with BIO_CTRL_PENDING, that number
|
||||
* can usually be treated as boolean.) */
|
||||
ret = (long) b->request;
|
||||
break;
|
||||
|
||||
case BIO_C_RESET_READ_REQUEST:
|
||||
/* Reset request. (Can be useful after read attempts
|
||||
* at the other side that are meant to be non-blocking,
|
||||
* e.g. when probing SSL_read to see if any data is
|
||||
* available.) */
|
||||
b->request = 0;
|
||||
ret = 1;
|
||||
break;
|
||||
|
||||
case BIO_C_SHUTDOWN_WR:
|
||||
/* similar to shutdown(..., SHUT_WR) */
|
||||
b->closed = 1;
|
||||
ret = 1;
|
||||
break;
|
||||
|
||||
/* standard CTRL codes follow */
|
||||
|
||||
case BIO_CTRL_RESET:
|
||||
if (b->buf != NULL) {
|
||||
b->len = 0;
|
||||
b->offset = 0;
|
||||
}
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
|
||||
case BIO_CTRL_GET_CLOSE:
|
||||
ret = bio->shutdown;
|
||||
break;
|
||||
|
||||
case BIO_CTRL_SET_CLOSE:
|
||||
bio->shutdown = (int) num;
|
||||
ret = 1;
|
||||
break;
|
||||
|
||||
case BIO_CTRL_PENDING:
|
||||
if (b->peer != NULL) {
|
||||
struct bio_bio_st *peer_b = b->peer->ptr;
|
||||
|
||||
ret = (long) peer_b->len;
|
||||
} else
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
case BIO_CTRL_WPENDING:
|
||||
if (b->buf != NULL)
|
||||
ret = (long) b->len;
|
||||
else
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
case BIO_CTRL_DUP:
|
||||
/* See BIO_dup_chain for circumstances we have to expect. */
|
||||
{
|
||||
BIO *other_bio = ptr;
|
||||
struct bio_bio_st *other_b;
|
||||
|
||||
assert(other_bio != NULL);
|
||||
other_b = other_bio->ptr;
|
||||
assert(other_b != NULL);
|
||||
|
||||
assert(other_b->buf == NULL); /* other_bio is always fresh */
|
||||
|
||||
other_b->size = b->size;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
break;
|
||||
|
||||
case BIO_CTRL_FLUSH:
|
||||
ret = 1;
|
||||
break;
|
||||
|
||||
case BIO_CTRL_EOF:
|
||||
{
|
||||
BIO *other_bio = ptr;
|
||||
|
||||
if (other_bio) {
|
||||
struct bio_bio_st *other_b = other_bio->ptr;
|
||||
|
||||
assert(other_b != NULL);
|
||||
ret = other_b->len == 0 && other_b->closed;
|
||||
} else
|
||||
ret = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
bio_puts(BIO *bio, const char *str)
|
||||
{
|
||||
return bio_write(bio, str, strlen(str));
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
bio_make_pair(BIO *bio1, BIO *bio2)
|
||||
{
|
||||
struct bio_bio_st *b1, *b2;
|
||||
|
||||
assert(bio1 != NULL);
|
||||
assert(bio2 != NULL);
|
||||
|
||||
b1 = bio1->ptr;
|
||||
b2 = bio2->ptr;
|
||||
|
||||
if (b1->peer != NULL || b2->peer != NULL) {
|
||||
BIOerror(BIO_R_IN_USE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (b1->buf == NULL) {
|
||||
b1->buf = malloc(b1->size);
|
||||
if (b1->buf == NULL) {
|
||||
BIOerror(ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
b1->len = 0;
|
||||
b1->offset = 0;
|
||||
}
|
||||
|
||||
if (b2->buf == NULL) {
|
||||
b2->buf = malloc(b2->size);
|
||||
if (b2->buf == NULL) {
|
||||
BIOerror(ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
b2->len = 0;
|
||||
b2->offset = 0;
|
||||
}
|
||||
|
||||
b1->peer = bio2;
|
||||
b1->closed = 0;
|
||||
b1->request = 0;
|
||||
b2->peer = bio1;
|
||||
b2->closed = 0;
|
||||
b2->request = 0;
|
||||
|
||||
bio1->init = 1;
|
||||
bio2->init = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
bio_destroy_pair(BIO *bio)
|
||||
{
|
||||
struct bio_bio_st *b = bio->ptr;
|
||||
|
||||
if (b != NULL) {
|
||||
BIO *peer_bio = b->peer;
|
||||
|
||||
if (peer_bio != NULL) {
|
||||
struct bio_bio_st *peer_b = peer_bio->ptr;
|
||||
|
||||
assert(peer_b != NULL);
|
||||
assert(peer_b->peer == bio);
|
||||
|
||||
peer_b->peer = NULL;
|
||||
peer_bio->init = 0;
|
||||
assert(peer_b->buf != NULL);
|
||||
peer_b->len = 0;
|
||||
peer_b->offset = 0;
|
||||
|
||||
b->peer = NULL;
|
||||
bio->init = 0;
|
||||
assert(b->buf != NULL);
|
||||
b->len = 0;
|
||||
b->offset = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Exported convenience functions */
|
||||
int
|
||||
BIO_new_bio_pair(BIO **bio1_p, size_t writebuf1, BIO **bio2_p, size_t writebuf2)
|
||||
{
|
||||
BIO *bio1 = NULL, *bio2 = NULL;
|
||||
long r;
|
||||
int ret = 0;
|
||||
|
||||
bio1 = BIO_new(BIO_s_bio());
|
||||
if (bio1 == NULL)
|
||||
goto err;
|
||||
bio2 = BIO_new(BIO_s_bio());
|
||||
if (bio2 == NULL)
|
||||
goto err;
|
||||
|
||||
if (writebuf1) {
|
||||
r = BIO_set_write_buf_size(bio1, writebuf1);
|
||||
if (!r)
|
||||
goto err;
|
||||
}
|
||||
if (writebuf2) {
|
||||
r = BIO_set_write_buf_size(bio2, writebuf2);
|
||||
if (!r)
|
||||
goto err;
|
||||
}
|
||||
|
||||
r = BIO_make_bio_pair(bio1, bio2);
|
||||
if (!r)
|
||||
goto err;
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
if (ret == 0) {
|
||||
if (bio1) {
|
||||
BIO_free(bio1);
|
||||
bio1 = NULL;
|
||||
}
|
||||
if (bio2) {
|
||||
BIO_free(bio2);
|
||||
bio2 = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
*bio1_p = bio1;
|
||||
*bio2_p = bio2;
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t
|
||||
BIO_ctrl_get_write_guarantee(BIO *bio)
|
||||
{
|
||||
return BIO_ctrl(bio, BIO_C_GET_WRITE_GUARANTEE, 0, NULL);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_ctrl_get_write_guarantee);
|
||||
|
||||
size_t
|
||||
BIO_ctrl_get_read_request(BIO *bio)
|
||||
{
|
||||
return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_ctrl_get_read_request);
|
||||
|
||||
int
|
||||
BIO_ctrl_reset_read_request(BIO *bio)
|
||||
{
|
||||
return (BIO_ctrl(bio, BIO_C_RESET_READ_REQUEST, 0, NULL) != 0);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_ctrl_reset_read_request);
|
598
crypto/bio/bss_conn.c
Normal file
598
crypto/bio/bss_conn.c
Normal file
@@ -0,0 +1,598 @@
|
||||
/* $OpenBSD: bss_conn.c,v 1.39 2023/07/07 19:37:53 beck Exp $ */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/buffer.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "bio_local.h"
|
||||
|
||||
#define SOCKET_PROTOCOL IPPROTO_TCP
|
||||
|
||||
typedef struct bio_connect_st {
|
||||
int state;
|
||||
|
||||
char *param_hostname;
|
||||
char *param_port;
|
||||
int nbio;
|
||||
|
||||
unsigned char ip[4];
|
||||
unsigned short port;
|
||||
|
||||
struct sockaddr_in them;
|
||||
|
||||
/* int socket; this will be kept in bio->num so that it is
|
||||
* compatible with the bss_sock bio */
|
||||
|
||||
/* called when the connection is initially made
|
||||
* callback(BIO,state,ret); The callback should return
|
||||
* 'ret'. state is for compatibility with the ssl info_callback */
|
||||
BIO_info_cb *info_callback;
|
||||
} BIO_CONNECT;
|
||||
|
||||
static int conn_write(BIO *h, const char *buf, int num);
|
||||
static int conn_read(BIO *h, char *buf, int size);
|
||||
static int conn_puts(BIO *h, const char *str);
|
||||
static long conn_ctrl(BIO *h, int cmd, long arg1, void *arg2);
|
||||
static int conn_new(BIO *h);
|
||||
static int conn_free(BIO *data);
|
||||
static long conn_callback_ctrl(BIO *h, int cmd, BIO_info_cb *);
|
||||
|
||||
static int conn_state(BIO *b, BIO_CONNECT *c);
|
||||
static void conn_close_socket(BIO *data);
|
||||
BIO_CONNECT *BIO_CONNECT_new(void);
|
||||
void BIO_CONNECT_free(BIO_CONNECT *a);
|
||||
|
||||
static const BIO_METHOD methods_connectp = {
|
||||
.type = BIO_TYPE_CONNECT,
|
||||
.name = "socket connect",
|
||||
.bwrite = conn_write,
|
||||
.bread = conn_read,
|
||||
.bputs = conn_puts,
|
||||
.ctrl = conn_ctrl,
|
||||
.create = conn_new,
|
||||
.destroy = conn_free,
|
||||
.callback_ctrl = conn_callback_ctrl
|
||||
};
|
||||
|
||||
static int
|
||||
conn_state(BIO *b, BIO_CONNECT *c)
|
||||
{
|
||||
int ret = -1, i;
|
||||
unsigned long l;
|
||||
char *p, *q;
|
||||
BIO_info_cb *cb = NULL;
|
||||
|
||||
if (c->info_callback != NULL)
|
||||
cb = c->info_callback;
|
||||
|
||||
for (;;) {
|
||||
switch (c->state) {
|
||||
case BIO_CONN_S_BEFORE:
|
||||
p = c->param_hostname;
|
||||
if (p == NULL) {
|
||||
BIOerror(BIO_R_NO_HOSTNAME_SPECIFIED);
|
||||
goto exit_loop;
|
||||
}
|
||||
for (; *p != '\0'; p++) {
|
||||
if ((*p == ':') || (*p == '/'))
|
||||
break;
|
||||
}
|
||||
|
||||
i= *p;
|
||||
if ((i == ':') || (i == '/')) {
|
||||
*(p++) = '\0';
|
||||
if (i == ':') {
|
||||
for (q = p; *q; q++)
|
||||
if (*q == '/') {
|
||||
*q = '\0';
|
||||
break;
|
||||
}
|
||||
free(c->param_port);
|
||||
c->param_port = strdup(p);
|
||||
}
|
||||
}
|
||||
|
||||
if (c->param_port == NULL) {
|
||||
BIOerror(BIO_R_NO_PORT_SPECIFIED);
|
||||
ERR_asprintf_error_data("host=%s",
|
||||
c->param_hostname);
|
||||
goto exit_loop;
|
||||
}
|
||||
c->state = BIO_CONN_S_GET_IP;
|
||||
break;
|
||||
|
||||
case BIO_CONN_S_GET_IP:
|
||||
if (BIO_get_host_ip(c->param_hostname, &(c->ip[0])) <= 0)
|
||||
goto exit_loop;
|
||||
c->state = BIO_CONN_S_GET_PORT;
|
||||
break;
|
||||
|
||||
case BIO_CONN_S_GET_PORT:
|
||||
if (c->param_port == NULL) {
|
||||
/* abort(); */
|
||||
goto exit_loop;
|
||||
} else if (BIO_get_port(c->param_port, &c->port) <= 0)
|
||||
goto exit_loop;
|
||||
c->state = BIO_CONN_S_CREATE_SOCKET;
|
||||
break;
|
||||
|
||||
case BIO_CONN_S_CREATE_SOCKET:
|
||||
/* now setup address */
|
||||
memset((char *)&c->them, 0, sizeof(c->them));
|
||||
c->them.sin_family = AF_INET;
|
||||
c->them.sin_port = htons((unsigned short)c->port);
|
||||
l = (unsigned long)
|
||||
((unsigned long)c->ip[0] << 24L)|
|
||||
((unsigned long)c->ip[1] << 16L)|
|
||||
((unsigned long)c->ip[2] << 8L)|
|
||||
((unsigned long)c->ip[3]);
|
||||
c->them.sin_addr.s_addr = htonl(l);
|
||||
c->state = BIO_CONN_S_CREATE_SOCKET;
|
||||
|
||||
ret = socket(AF_INET, SOCK_STREAM, SOCKET_PROTOCOL);
|
||||
if (ret == -1) {
|
||||
SYSerror(errno);
|
||||
ERR_asprintf_error_data("host=%s:%s",
|
||||
c->param_hostname, c->param_port);
|
||||
BIOerror(BIO_R_UNABLE_TO_CREATE_SOCKET);
|
||||
goto exit_loop;
|
||||
}
|
||||
b->num = ret;
|
||||
c->state = BIO_CONN_S_NBIO;
|
||||
break;
|
||||
|
||||
case BIO_CONN_S_NBIO:
|
||||
if (c->nbio) {
|
||||
if (!BIO_socket_nbio(b->num, 1)) {
|
||||
BIOerror(BIO_R_ERROR_SETTING_NBIO);
|
||||
ERR_asprintf_error_data("host=%s:%s",
|
||||
c->param_hostname, c->param_port);
|
||||
goto exit_loop;
|
||||
}
|
||||
}
|
||||
c->state = BIO_CONN_S_CONNECT;
|
||||
|
||||
#if defined(SO_KEEPALIVE)
|
||||
i = 1;
|
||||
i = setsockopt(b->num, SOL_SOCKET, SO_KEEPALIVE, &i, sizeof(i));
|
||||
if (i < 0) {
|
||||
SYSerror(errno);
|
||||
ERR_asprintf_error_data("host=%s:%s",
|
||||
c->param_hostname, c->param_port);
|
||||
BIOerror(BIO_R_KEEPALIVE);
|
||||
goto exit_loop;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
case BIO_CONN_S_CONNECT:
|
||||
BIO_clear_retry_flags(b);
|
||||
ret = connect(b->num,
|
||||
(struct sockaddr *)&c->them,
|
||||
sizeof(c->them));
|
||||
b->retry_reason = 0;
|
||||
if (ret < 0) {
|
||||
if (BIO_sock_should_retry(ret)) {
|
||||
BIO_set_retry_special(b);
|
||||
c->state = BIO_CONN_S_BLOCKED_CONNECT;
|
||||
b->retry_reason = BIO_RR_CONNECT;
|
||||
} else {
|
||||
SYSerror(errno);
|
||||
ERR_asprintf_error_data("host=%s:%s",
|
||||
c->param_hostname, c->param_port);
|
||||
BIOerror(BIO_R_CONNECT_ERROR);
|
||||
}
|
||||
goto exit_loop;
|
||||
} else
|
||||
c->state = BIO_CONN_S_OK;
|
||||
break;
|
||||
|
||||
case BIO_CONN_S_BLOCKED_CONNECT:
|
||||
i = BIO_sock_error(b->num);
|
||||
if (i) {
|
||||
BIO_clear_retry_flags(b);
|
||||
SYSerror(i);
|
||||
ERR_asprintf_error_data("host=%s:%s",
|
||||
c->param_hostname, c->param_port);
|
||||
BIOerror(BIO_R_NBIO_CONNECT_ERROR);
|
||||
ret = 0;
|
||||
goto exit_loop;
|
||||
} else
|
||||
c->state = BIO_CONN_S_OK;
|
||||
break;
|
||||
|
||||
case BIO_CONN_S_OK:
|
||||
ret = 1;
|
||||
goto exit_loop;
|
||||
default:
|
||||
/* abort(); */
|
||||
goto exit_loop;
|
||||
}
|
||||
|
||||
if (cb != NULL) {
|
||||
if (!(ret = cb((BIO *)b, c->state, ret)))
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
/* Loop does not exit */
|
||||
exit_loop:
|
||||
if (cb != NULL)
|
||||
ret = cb((BIO *)b, c->state, ret);
|
||||
end:
|
||||
return (ret);
|
||||
}
|
||||
|
||||
BIO_CONNECT *
|
||||
BIO_CONNECT_new(void)
|
||||
{
|
||||
BIO_CONNECT *ret;
|
||||
|
||||
if ((ret = malloc(sizeof(BIO_CONNECT))) == NULL)
|
||||
return (NULL);
|
||||
ret->state = BIO_CONN_S_BEFORE;
|
||||
ret->param_hostname = NULL;
|
||||
ret->param_port = NULL;
|
||||
ret->info_callback = NULL;
|
||||
ret->nbio = 0;
|
||||
ret->ip[0] = 0;
|
||||
ret->ip[1] = 0;
|
||||
ret->ip[2] = 0;
|
||||
ret->ip[3] = 0;
|
||||
ret->port = 0;
|
||||
memset((char *)&ret->them, 0, sizeof(ret->them));
|
||||
return (ret);
|
||||
}
|
||||
|
||||
void
|
||||
BIO_CONNECT_free(BIO_CONNECT *a)
|
||||
{
|
||||
if (a == NULL)
|
||||
return;
|
||||
|
||||
free(a->param_hostname);
|
||||
free(a->param_port);
|
||||
free(a);
|
||||
}
|
||||
|
||||
const BIO_METHOD *
|
||||
BIO_s_connect(void)
|
||||
{
|
||||
return (&methods_connectp);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_s_connect);
|
||||
|
||||
static int
|
||||
conn_new(BIO *bi)
|
||||
{
|
||||
bi->init = 0;
|
||||
bi->num = -1;
|
||||
bi->flags = 0;
|
||||
if ((bi->ptr = (char *)BIO_CONNECT_new()) == NULL)
|
||||
return (0);
|
||||
else
|
||||
return (1);
|
||||
}
|
||||
|
||||
static void
|
||||
conn_close_socket(BIO *bio)
|
||||
{
|
||||
BIO_CONNECT *c;
|
||||
|
||||
c = (BIO_CONNECT *)bio->ptr;
|
||||
if (bio->num != -1) {
|
||||
/* Only do a shutdown if things were established */
|
||||
if (c->state == BIO_CONN_S_OK)
|
||||
shutdown(bio->num, SHUT_RDWR);
|
||||
close(bio->num);
|
||||
bio->num = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
conn_free(BIO *a)
|
||||
{
|
||||
BIO_CONNECT *data;
|
||||
|
||||
if (a == NULL)
|
||||
return (0);
|
||||
data = (BIO_CONNECT *)a->ptr;
|
||||
|
||||
if (a->shutdown) {
|
||||
conn_close_socket(a);
|
||||
BIO_CONNECT_free(data);
|
||||
a->ptr = NULL;
|
||||
a->flags = 0;
|
||||
a->init = 0;
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
conn_read(BIO *b, char *out, int outl)
|
||||
{
|
||||
int ret = 0;
|
||||
BIO_CONNECT *data;
|
||||
|
||||
data = (BIO_CONNECT *)b->ptr;
|
||||
if (data->state != BIO_CONN_S_OK) {
|
||||
ret = conn_state(b, data);
|
||||
if (ret <= 0)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
if (out != NULL) {
|
||||
errno = 0;
|
||||
ret = read(b->num, out, outl);
|
||||
BIO_clear_retry_flags(b);
|
||||
if (ret <= 0) {
|
||||
if (BIO_sock_should_retry(ret))
|
||||
BIO_set_retry_read(b);
|
||||
}
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
conn_write(BIO *b, const char *in, int inl)
|
||||
{
|
||||
int ret;
|
||||
BIO_CONNECT *data;
|
||||
|
||||
data = (BIO_CONNECT *)b->ptr;
|
||||
if (data->state != BIO_CONN_S_OK) {
|
||||
ret = conn_state(b, data);
|
||||
if (ret <= 0)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
ret = write(b->num, in, inl);
|
||||
BIO_clear_retry_flags(b);
|
||||
if (ret <= 0) {
|
||||
if (BIO_sock_should_retry(ret))
|
||||
BIO_set_retry_write(b);
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static long
|
||||
conn_ctrl(BIO *b, int cmd, long num, void *ptr)
|
||||
{
|
||||
BIO *dbio;
|
||||
int *ip;
|
||||
const char **pptr;
|
||||
long ret = 1;
|
||||
BIO_CONNECT *data;
|
||||
|
||||
data = (BIO_CONNECT *)b->ptr;
|
||||
|
||||
switch (cmd) {
|
||||
case BIO_CTRL_RESET:
|
||||
ret = 0;
|
||||
data->state = BIO_CONN_S_BEFORE;
|
||||
conn_close_socket(b);
|
||||
b->flags = 0;
|
||||
break;
|
||||
case BIO_C_DO_STATE_MACHINE:
|
||||
/* use this one to start the connection */
|
||||
if (data->state != BIO_CONN_S_OK)
|
||||
ret = (long)conn_state(b, data);
|
||||
else
|
||||
ret = 1;
|
||||
break;
|
||||
case BIO_C_GET_CONNECT:
|
||||
if (ptr != NULL) {
|
||||
pptr = (const char **)ptr;
|
||||
if (num == 0) {
|
||||
*pptr = data->param_hostname;
|
||||
|
||||
} else if (num == 1) {
|
||||
*pptr = data->param_port;
|
||||
} else if (num == 2) {
|
||||
*pptr = (char *)&(data->ip[0]);
|
||||
} else if (num == 3) {
|
||||
*((int *)ptr) = data->port;
|
||||
}
|
||||
if ((!b->init) || (ptr == NULL))
|
||||
*pptr = "not initialized";
|
||||
ret = 1;
|
||||
}
|
||||
break;
|
||||
case BIO_C_SET_CONNECT:
|
||||
if (ptr != NULL) {
|
||||
b->init = 1;
|
||||
if (num == 0) {
|
||||
free(data->param_hostname);
|
||||
data->param_hostname = strdup(ptr);
|
||||
} else if (num == 1) {
|
||||
free(data->param_port);
|
||||
data->param_port = strdup(ptr);
|
||||
} else if (num == 2) {
|
||||
unsigned char *p = ptr;
|
||||
free(data->param_hostname);
|
||||
if (asprintf(&data->param_hostname,
|
||||
"%u.%u.%u.%u", p[0], p[1],
|
||||
p[2], p[3]) == -1)
|
||||
data->param_hostname = NULL;
|
||||
memcpy(&(data->ip[0]), ptr, 4);
|
||||
} else if (num == 3) {
|
||||
free(data->param_port);
|
||||
data->port= *(int *)ptr;
|
||||
if (asprintf(&data->param_port, "%d",
|
||||
data->port) == -1)
|
||||
data->param_port = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BIO_C_SET_NBIO:
|
||||
data->nbio = (int)num;
|
||||
break;
|
||||
case BIO_C_GET_FD:
|
||||
if (b->init) {
|
||||
ip = (int *)ptr;
|
||||
if (ip != NULL)
|
||||
*ip = b->num;
|
||||
ret = b->num;
|
||||
} else
|
||||
ret = -1;
|
||||
break;
|
||||
case BIO_CTRL_GET_CLOSE:
|
||||
ret = b->shutdown;
|
||||
break;
|
||||
case BIO_CTRL_SET_CLOSE:
|
||||
b->shutdown = (int)num;
|
||||
break;
|
||||
case BIO_CTRL_PENDING:
|
||||
case BIO_CTRL_WPENDING:
|
||||
ret = 0;
|
||||
break;
|
||||
case BIO_CTRL_FLUSH:
|
||||
break;
|
||||
case BIO_CTRL_DUP:
|
||||
{
|
||||
dbio = (BIO *)ptr;
|
||||
if (data->param_port)
|
||||
BIO_set_conn_port(dbio, data->param_port);
|
||||
if (data->param_hostname)
|
||||
BIO_set_conn_hostname(dbio,
|
||||
data->param_hostname);
|
||||
BIO_set_nbio(dbio, data->nbio);
|
||||
(void)BIO_set_info_callback(dbio, data->info_callback);
|
||||
}
|
||||
break;
|
||||
case BIO_CTRL_SET_CALLBACK:
|
||||
{
|
||||
#if 0 /* FIXME: Should this be used? -- Richard Levitte */
|
||||
BIOerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
||||
ret = -1;
|
||||
#else
|
||||
ret = 0;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case BIO_CTRL_GET_CALLBACK:
|
||||
{
|
||||
BIO_info_cb **fptr = ptr;
|
||||
|
||||
*fptr = data->info_callback;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static long
|
||||
conn_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
|
||||
{
|
||||
long ret = 1;
|
||||
BIO_CONNECT *data;
|
||||
|
||||
data = (BIO_CONNECT *)b->ptr;
|
||||
|
||||
switch (cmd) {
|
||||
case BIO_CTRL_SET_CALLBACK:
|
||||
data->info_callback = (BIO_info_cb *)fp;
|
||||
break;
|
||||
default:
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
conn_puts(BIO *bp, const char *str)
|
||||
{
|
||||
int n, ret;
|
||||
|
||||
n = strlen(str);
|
||||
ret = conn_write(bp, str, n);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
BIO *
|
||||
BIO_new_connect(const char *str)
|
||||
{
|
||||
BIO *ret;
|
||||
|
||||
ret = BIO_new(BIO_s_connect());
|
||||
if (ret == NULL)
|
||||
return (NULL);
|
||||
if (BIO_set_conn_hostname(ret, str))
|
||||
return (ret);
|
||||
else {
|
||||
BIO_free(ret);
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_new_connect);
|
663
crypto/bio/bss_dgram.c
Normal file
663
crypto/bio/bss_dgram.c
Normal file
@@ -0,0 +1,663 @@
|
||||
/* $OpenBSD: bss_dgram.c,v 1.45 2023/07/05 21:23:37 beck Exp $ */
|
||||
/*
|
||||
* DTLS implementation written by Nagendra Modadugu
|
||||
* (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1999-2005 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <openssl/opensslconf.h>
|
||||
|
||||
#include <openssl/bio.h>
|
||||
|
||||
#include "bio_local.h"
|
||||
|
||||
#ifndef OPENSSL_NO_DGRAM
|
||||
|
||||
|
||||
static int dgram_write(BIO *h, const char *buf, int num);
|
||||
static int dgram_read(BIO *h, char *buf, int size);
|
||||
static int dgram_puts(BIO *h, const char *str);
|
||||
static long dgram_ctrl(BIO *h, int cmd, long arg1, void *arg2);
|
||||
static int dgram_new(BIO *h);
|
||||
static int dgram_free(BIO *data);
|
||||
static int dgram_clear(BIO *bio);
|
||||
|
||||
|
||||
static int BIO_dgram_should_retry(int s);
|
||||
|
||||
static const BIO_METHOD methods_dgramp = {
|
||||
.type = BIO_TYPE_DGRAM,
|
||||
.name = "datagram socket",
|
||||
.bwrite = dgram_write,
|
||||
.bread = dgram_read,
|
||||
.bputs = dgram_puts,
|
||||
.ctrl = dgram_ctrl,
|
||||
.create = dgram_new,
|
||||
.destroy = dgram_free
|
||||
};
|
||||
|
||||
|
||||
typedef struct bio_dgram_data_st {
|
||||
union {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_in sa_in;
|
||||
struct sockaddr_in6 sa_in6;
|
||||
} peer;
|
||||
unsigned int connected;
|
||||
unsigned int _errno;
|
||||
unsigned int mtu;
|
||||
struct timeval next_timeout;
|
||||
struct timeval socket_timeout;
|
||||
} bio_dgram_data;
|
||||
|
||||
|
||||
const BIO_METHOD *
|
||||
BIO_s_datagram(void)
|
||||
{
|
||||
return (&methods_dgramp);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_s_datagram);
|
||||
|
||||
BIO *
|
||||
BIO_new_dgram(int fd, int close_flag)
|
||||
{
|
||||
BIO *ret;
|
||||
|
||||
ret = BIO_new(BIO_s_datagram());
|
||||
if (ret == NULL)
|
||||
return (NULL);
|
||||
BIO_set_fd(ret, fd, close_flag);
|
||||
return (ret);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_new_dgram);
|
||||
|
||||
static int
|
||||
dgram_new(BIO *bi)
|
||||
{
|
||||
bio_dgram_data *data = NULL;
|
||||
|
||||
bi->init = 0;
|
||||
bi->num = 0;
|
||||
data = calloc(1, sizeof(bio_dgram_data));
|
||||
if (data == NULL)
|
||||
return 0;
|
||||
bi->ptr = data;
|
||||
|
||||
bi->flags = 0;
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
dgram_free(BIO *a)
|
||||
{
|
||||
bio_dgram_data *data;
|
||||
|
||||
if (a == NULL)
|
||||
return (0);
|
||||
if (!dgram_clear(a))
|
||||
return 0;
|
||||
|
||||
data = (bio_dgram_data *)a->ptr;
|
||||
free(data);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
dgram_clear(BIO *a)
|
||||
{
|
||||
if (a == NULL)
|
||||
return (0);
|
||||
if (a->shutdown) {
|
||||
if (a->init) {
|
||||
shutdown(a->num, SHUT_RDWR);
|
||||
close(a->num);
|
||||
}
|
||||
a->init = 0;
|
||||
a->flags = 0;
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
static void
|
||||
dgram_adjust_rcv_timeout(BIO *b)
|
||||
{
|
||||
#if defined(SO_RCVTIMEO)
|
||||
bio_dgram_data *data = (bio_dgram_data *)b->ptr;
|
||||
|
||||
/* Is a timer active? */
|
||||
if (data->next_timeout.tv_sec > 0 || data->next_timeout.tv_usec > 0) {
|
||||
struct timeval timenow, timeleft;
|
||||
|
||||
/* Read current socket timeout */
|
||||
socklen_t sz = sizeof(data->socket_timeout);
|
||||
if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
|
||||
&(data->socket_timeout), &sz) < 0) {
|
||||
perror("getsockopt");
|
||||
}
|
||||
|
||||
/* Get current time */
|
||||
gettimeofday(&timenow, NULL);
|
||||
|
||||
/* Calculate time left until timer expires */
|
||||
memcpy(&timeleft, &(data->next_timeout), sizeof(struct timeval));
|
||||
timeleft.tv_sec -= timenow.tv_sec;
|
||||
timeleft.tv_usec -= timenow.tv_usec;
|
||||
if (timeleft.tv_usec < 0) {
|
||||
timeleft.tv_sec--;
|
||||
timeleft.tv_usec += 1000000;
|
||||
}
|
||||
|
||||
if (timeleft.tv_sec < 0) {
|
||||
timeleft.tv_sec = 0;
|
||||
timeleft.tv_usec = 1;
|
||||
}
|
||||
|
||||
/* Adjust socket timeout if next handshake message timer
|
||||
* will expire earlier.
|
||||
*/
|
||||
if ((data->socket_timeout.tv_sec == 0 &&
|
||||
data->socket_timeout.tv_usec == 0) ||
|
||||
(data->socket_timeout.tv_sec > timeleft.tv_sec) ||
|
||||
(data->socket_timeout.tv_sec == timeleft.tv_sec &&
|
||||
data->socket_timeout.tv_usec >= timeleft.tv_usec)) {
|
||||
if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
|
||||
&timeleft, sizeof(struct timeval)) < 0) {
|
||||
perror("setsockopt");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
dgram_reset_rcv_timeout(BIO *b)
|
||||
{
|
||||
#if defined(SO_RCVTIMEO)
|
||||
bio_dgram_data *data = (bio_dgram_data *)b->ptr;
|
||||
|
||||
/* Is a timer active? */
|
||||
if (data->next_timeout.tv_sec > 0 || data->next_timeout.tv_usec > 0) {
|
||||
if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
|
||||
&(data->socket_timeout), sizeof(struct timeval)) < 0) {
|
||||
perror("setsockopt");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
dgram_read(BIO *b, char *out, int outl)
|
||||
{
|
||||
int ret = 0;
|
||||
bio_dgram_data *data = (bio_dgram_data *)b->ptr;
|
||||
|
||||
struct {
|
||||
socklen_t len;
|
||||
union {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_in sa_in;
|
||||
struct sockaddr_in6 sa_in6;
|
||||
} peer;
|
||||
} sa;
|
||||
|
||||
sa.len = sizeof(sa.peer);
|
||||
|
||||
if (out != NULL) {
|
||||
errno = 0;
|
||||
memset(&sa.peer, 0, sizeof(sa.peer));
|
||||
dgram_adjust_rcv_timeout(b);
|
||||
ret = recvfrom(b->num, out, outl, 0, &sa.peer.sa, &sa.len);
|
||||
|
||||
if (! data->connected && ret >= 0)
|
||||
BIO_ctrl(b, BIO_CTRL_DGRAM_SET_PEER, 0, &sa.peer);
|
||||
|
||||
BIO_clear_retry_flags(b);
|
||||
if (ret < 0) {
|
||||
if (BIO_dgram_should_retry(ret)) {
|
||||
BIO_set_retry_read(b);
|
||||
data->_errno = errno;
|
||||
}
|
||||
}
|
||||
|
||||
dgram_reset_rcv_timeout(b);
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
dgram_write(BIO *b, const char *in, int inl)
|
||||
{
|
||||
int ret;
|
||||
bio_dgram_data *data = (bio_dgram_data *)b->ptr;
|
||||
errno = 0;
|
||||
|
||||
if (data->connected)
|
||||
ret = write(b->num, in, inl);
|
||||
else {
|
||||
int peerlen = sizeof(data->peer);
|
||||
|
||||
if (data->peer.sa.sa_family == AF_INET)
|
||||
peerlen = sizeof(data->peer.sa_in);
|
||||
else if (data->peer.sa.sa_family == AF_INET6)
|
||||
peerlen = sizeof(data->peer.sa_in6);
|
||||
ret = sendto(b->num, in, inl, 0, &data->peer.sa, peerlen);
|
||||
}
|
||||
|
||||
BIO_clear_retry_flags(b);
|
||||
if (ret <= 0) {
|
||||
if (BIO_dgram_should_retry(ret)) {
|
||||
BIO_set_retry_write(b);
|
||||
|
||||
data->_errno = errno;
|
||||
/*
|
||||
* higher layers are responsible for querying MTU,
|
||||
* if necessary
|
||||
*/
|
||||
}
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static long
|
||||
dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
|
||||
{
|
||||
long ret = 1;
|
||||
int *ip;
|
||||
struct sockaddr *to = NULL;
|
||||
bio_dgram_data *data = NULL;
|
||||
#if (defined(IP_MTU_DISCOVER) || defined(IP_MTU))
|
||||
int sockopt_val = 0;
|
||||
socklen_t sockopt_len; /* assume that system supporting IP_MTU is
|
||||
* modern enough to define socklen_t */
|
||||
socklen_t addr_len;
|
||||
union {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_in s4;
|
||||
struct sockaddr_in6 s6;
|
||||
} addr;
|
||||
#endif
|
||||
|
||||
data = (bio_dgram_data *)b->ptr;
|
||||
|
||||
switch (cmd) {
|
||||
case BIO_CTRL_RESET:
|
||||
num = 0;
|
||||
case BIO_C_FILE_SEEK:
|
||||
ret = 0;
|
||||
break;
|
||||
case BIO_C_FILE_TELL:
|
||||
case BIO_CTRL_INFO:
|
||||
ret = 0;
|
||||
break;
|
||||
case BIO_C_SET_FD:
|
||||
dgram_clear(b);
|
||||
b->num= *((int *)ptr);
|
||||
b->shutdown = (int)num;
|
||||
b->init = 1;
|
||||
break;
|
||||
case BIO_C_GET_FD:
|
||||
if (b->init) {
|
||||
ip = (int *)ptr;
|
||||
if (ip != NULL)
|
||||
*ip = b->num;
|
||||
ret = b->num;
|
||||
} else
|
||||
ret = -1;
|
||||
break;
|
||||
case BIO_CTRL_GET_CLOSE:
|
||||
ret = b->shutdown;
|
||||
break;
|
||||
case BIO_CTRL_SET_CLOSE:
|
||||
b->shutdown = (int)num;
|
||||
break;
|
||||
case BIO_CTRL_PENDING:
|
||||
case BIO_CTRL_WPENDING:
|
||||
ret = 0;
|
||||
break;
|
||||
case BIO_CTRL_DUP:
|
||||
case BIO_CTRL_FLUSH:
|
||||
ret = 1;
|
||||
break;
|
||||
case BIO_CTRL_DGRAM_CONNECT:
|
||||
to = (struct sockaddr *)ptr;
|
||||
switch (to->sa_family) {
|
||||
case AF_INET:
|
||||
memcpy(&data->peer, to, sizeof(data->peer.sa_in));
|
||||
break;
|
||||
case AF_INET6:
|
||||
memcpy(&data->peer, to, sizeof(data->peer.sa_in6));
|
||||
break;
|
||||
default:
|
||||
memcpy(&data->peer, to, sizeof(data->peer.sa));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
/* (Linux)kernel sets DF bit on outgoing IP packets */
|
||||
case BIO_CTRL_DGRAM_MTU_DISCOVER:
|
||||
#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO)
|
||||
addr_len = (socklen_t)sizeof(addr);
|
||||
memset((void *)&addr, 0, sizeof(addr));
|
||||
if (getsockname(b->num, &addr.sa, &addr_len) < 0) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
switch (addr.sa.sa_family) {
|
||||
case AF_INET:
|
||||
sockopt_val = IP_PMTUDISC_DO;
|
||||
ret = setsockopt(b->num, IPPROTO_IP, IP_MTU_DISCOVER,
|
||||
&sockopt_val, sizeof(sockopt_val));
|
||||
if (ret < 0)
|
||||
perror("setsockopt");
|
||||
break;
|
||||
#if defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO)
|
||||
case AF_INET6:
|
||||
sockopt_val = IPV6_PMTUDISC_DO;
|
||||
ret = setsockopt(b->num, IPPROTO_IPV6,
|
||||
IPV6_MTU_DISCOVER, &sockopt_val,
|
||||
sizeof(sockopt_val));
|
||||
if (ret < 0)
|
||||
perror("setsockopt");
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
ret = -1;
|
||||
#endif
|
||||
break;
|
||||
case BIO_CTRL_DGRAM_QUERY_MTU:
|
||||
#if defined(IP_MTU)
|
||||
addr_len = (socklen_t)sizeof(addr);
|
||||
memset((void *)&addr, 0, sizeof(addr));
|
||||
if (getsockname(b->num, &addr.sa, &addr_len) < 0) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
sockopt_len = sizeof(sockopt_val);
|
||||
switch (addr.sa.sa_family) {
|
||||
case AF_INET:
|
||||
ret = getsockopt(b->num, IPPROTO_IP, IP_MTU,
|
||||
&sockopt_val, &sockopt_len);
|
||||
if (ret < 0 || sockopt_val < 0) {
|
||||
ret = 0;
|
||||
} else {
|
||||
/* we assume that the transport protocol is UDP and no
|
||||
* IP options are used.
|
||||
*/
|
||||
data->mtu = sockopt_val - 8 - 20;
|
||||
ret = data->mtu;
|
||||
}
|
||||
break;
|
||||
#if defined(IPV6_MTU)
|
||||
case AF_INET6:
|
||||
ret = getsockopt(b->num, IPPROTO_IPV6, IPV6_MTU,
|
||||
&sockopt_val, &sockopt_len);
|
||||
if (ret < 0 || sockopt_val < 0) {
|
||||
ret = 0;
|
||||
} else {
|
||||
/* we assume that the transport protocol is UDP and no
|
||||
* IPV6 options are used.
|
||||
*/
|
||||
data->mtu = sockopt_val - 8 - 40;
|
||||
ret = data->mtu;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
ret = 0;
|
||||
#endif
|
||||
break;
|
||||
case BIO_CTRL_DGRAM_GET_FALLBACK_MTU:
|
||||
switch (data->peer.sa.sa_family) {
|
||||
case AF_INET:
|
||||
ret = 576 - 20 - 8;
|
||||
break;
|
||||
case AF_INET6:
|
||||
#ifdef IN6_IS_ADDR_V4MAPPED
|
||||
if (IN6_IS_ADDR_V4MAPPED(&data->peer.sa_in6.sin6_addr))
|
||||
ret = 576 - 20 - 8;
|
||||
else
|
||||
#endif
|
||||
ret = 1280 - 40 - 8;
|
||||
break;
|
||||
default:
|
||||
ret = 576 - 20 - 8;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case BIO_CTRL_DGRAM_GET_MTU:
|
||||
return data->mtu;
|
||||
break;
|
||||
case BIO_CTRL_DGRAM_SET_MTU:
|
||||
data->mtu = num;
|
||||
ret = num;
|
||||
break;
|
||||
case BIO_CTRL_DGRAM_SET_CONNECTED:
|
||||
to = (struct sockaddr *)ptr;
|
||||
|
||||
if (to != NULL) {
|
||||
data->connected = 1;
|
||||
switch (to->sa_family) {
|
||||
case AF_INET:
|
||||
memcpy(&data->peer, to, sizeof(data->peer.sa_in));
|
||||
break;
|
||||
case AF_INET6:
|
||||
memcpy(&data->peer, to, sizeof(data->peer.sa_in6));
|
||||
break;
|
||||
default:
|
||||
memcpy(&data->peer, to, sizeof(data->peer.sa));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
data->connected = 0;
|
||||
memset(&(data->peer), 0, sizeof(data->peer));
|
||||
}
|
||||
break;
|
||||
case BIO_CTRL_DGRAM_GET_PEER:
|
||||
switch (data->peer.sa.sa_family) {
|
||||
case AF_INET:
|
||||
ret = sizeof(data->peer.sa_in);
|
||||
break;
|
||||
case AF_INET6:
|
||||
ret = sizeof(data->peer.sa_in6);
|
||||
break;
|
||||
default:
|
||||
ret = sizeof(data->peer.sa);
|
||||
break;
|
||||
}
|
||||
if (num == 0 || num > ret)
|
||||
num = ret;
|
||||
memcpy(ptr, &data->peer, (ret = num));
|
||||
break;
|
||||
case BIO_CTRL_DGRAM_SET_PEER:
|
||||
to = (struct sockaddr *) ptr;
|
||||
switch (to->sa_family) {
|
||||
case AF_INET:
|
||||
memcpy(&data->peer, to, sizeof(data->peer.sa_in));
|
||||
break;
|
||||
case AF_INET6:
|
||||
memcpy(&data->peer, to, sizeof(data->peer.sa_in6));
|
||||
break;
|
||||
default:
|
||||
memcpy(&data->peer, to, sizeof(data->peer.sa));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT:
|
||||
memcpy(&(data->next_timeout), ptr, sizeof(struct timeval));
|
||||
break;
|
||||
#if defined(SO_RCVTIMEO)
|
||||
case BIO_CTRL_DGRAM_SET_RECV_TIMEOUT:
|
||||
if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, ptr,
|
||||
sizeof(struct timeval)) < 0) {
|
||||
perror("setsockopt");
|
||||
ret = -1;
|
||||
}
|
||||
break;
|
||||
case BIO_CTRL_DGRAM_GET_RECV_TIMEOUT:
|
||||
{
|
||||
socklen_t sz = sizeof(struct timeval);
|
||||
if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
|
||||
ptr, &sz) < 0) {
|
||||
perror("getsockopt");
|
||||
ret = -1;
|
||||
} else
|
||||
ret = sz;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#if defined(SO_SNDTIMEO)
|
||||
case BIO_CTRL_DGRAM_SET_SEND_TIMEOUT:
|
||||
if (setsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, ptr,
|
||||
sizeof(struct timeval)) < 0) {
|
||||
perror("setsockopt");
|
||||
ret = -1;
|
||||
}
|
||||
break;
|
||||
case BIO_CTRL_DGRAM_GET_SEND_TIMEOUT:
|
||||
{
|
||||
socklen_t sz = sizeof(struct timeval);
|
||||
if (getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO,
|
||||
ptr, &sz) < 0) {
|
||||
perror("getsockopt");
|
||||
ret = -1;
|
||||
} else
|
||||
ret = sz;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP:
|
||||
/* fall-through */
|
||||
case BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP:
|
||||
if (data->_errno == EAGAIN) {
|
||||
ret = 1;
|
||||
data->_errno = 0;
|
||||
} else
|
||||
ret = 0;
|
||||
break;
|
||||
#ifdef EMSGSIZE
|
||||
case BIO_CTRL_DGRAM_MTU_EXCEEDED:
|
||||
if (data->_errno == EMSGSIZE) {
|
||||
ret = 1;
|
||||
data->_errno = 0;
|
||||
} else
|
||||
ret = 0;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
dgram_puts(BIO *bp, const char *str)
|
||||
{
|
||||
int n, ret;
|
||||
|
||||
n = strlen(str);
|
||||
ret = dgram_write(bp, str, n);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
BIO_dgram_should_retry(int i)
|
||||
{
|
||||
int err;
|
||||
|
||||
if ((i == 0) || (i == -1)) {
|
||||
err = errno;
|
||||
return (BIO_dgram_non_fatal_error(err));
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
BIO_dgram_non_fatal_error(int err)
|
||||
{
|
||||
switch (err) {
|
||||
case EINTR:
|
||||
case EAGAIN:
|
||||
case EINPROGRESS:
|
||||
case EALREADY:
|
||||
return (1);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_dgram_non_fatal_error);
|
||||
|
||||
#endif
|
273
crypto/bio/bss_fd.c
Normal file
273
crypto/bio/bss_fd.c
Normal file
@@ -0,0 +1,273 @@
|
||||
/* $OpenBSD: bss_fd.c,v 1.21 2023/07/05 21:23:37 beck Exp $ */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <openssl/opensslconf.h>
|
||||
|
||||
#include <openssl/bio.h>
|
||||
|
||||
#include "bio_local.h"
|
||||
|
||||
static int fd_write(BIO *h, const char *buf, int num);
|
||||
static int fd_read(BIO *h, char *buf, int size);
|
||||
static int fd_puts(BIO *h, const char *str);
|
||||
static int fd_gets(BIO *h, char *buf, int size);
|
||||
static long fd_ctrl(BIO *h, int cmd, long arg1, void *arg2);
|
||||
static int fd_new(BIO *h);
|
||||
static int fd_free(BIO *data);
|
||||
int BIO_fd_should_retry(int s);
|
||||
|
||||
static const BIO_METHOD methods_fdp = {
|
||||
.type = BIO_TYPE_FD,
|
||||
.name = "file descriptor",
|
||||
.bwrite = fd_write,
|
||||
.bread = fd_read,
|
||||
.bputs = fd_puts,
|
||||
.bgets = fd_gets,
|
||||
.ctrl = fd_ctrl,
|
||||
.create = fd_new,
|
||||
.destroy = fd_free
|
||||
};
|
||||
|
||||
const BIO_METHOD *
|
||||
BIO_s_fd(void)
|
||||
{
|
||||
return (&methods_fdp);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_s_fd);
|
||||
|
||||
BIO *
|
||||
BIO_new_fd(int fd, int close_flag)
|
||||
{
|
||||
BIO *ret;
|
||||
ret = BIO_new(BIO_s_fd());
|
||||
if (ret == NULL)
|
||||
return (NULL);
|
||||
BIO_set_fd(ret, fd, close_flag);
|
||||
return (ret);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_new_fd);
|
||||
|
||||
static int
|
||||
fd_new(BIO *bi)
|
||||
{
|
||||
bi->init = 0;
|
||||
bi->num = -1;
|
||||
bi->ptr = NULL;
|
||||
bi->flags=0;
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
fd_free(BIO *a)
|
||||
{
|
||||
if (a == NULL)
|
||||
return (0);
|
||||
if (a->shutdown) {
|
||||
if (a->init) {
|
||||
close(a->num);
|
||||
}
|
||||
a->init = 0;
|
||||
a->flags = 0;
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
fd_read(BIO *b, char *out, int outl)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (out != NULL) {
|
||||
errno = 0;
|
||||
ret = read(b->num, out, outl);
|
||||
BIO_clear_retry_flags(b);
|
||||
if (ret <= 0) {
|
||||
if (BIO_fd_should_retry(ret))
|
||||
BIO_set_retry_read(b);
|
||||
}
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
fd_write(BIO *b, const char *in, int inl)
|
||||
{
|
||||
int ret;
|
||||
errno = 0;
|
||||
ret = write(b->num, in, inl);
|
||||
BIO_clear_retry_flags(b);
|
||||
if (ret <= 0) {
|
||||
if (BIO_fd_should_retry(ret))
|
||||
BIO_set_retry_write(b);
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static long
|
||||
fd_ctrl(BIO *b, int cmd, long num, void *ptr)
|
||||
{
|
||||
long ret = 1;
|
||||
int *ip;
|
||||
|
||||
switch (cmd) {
|
||||
case BIO_CTRL_RESET:
|
||||
num = 0;
|
||||
case BIO_C_FILE_SEEK:
|
||||
ret = (long)lseek(b->num, num, 0);
|
||||
break;
|
||||
case BIO_C_FILE_TELL:
|
||||
case BIO_CTRL_INFO:
|
||||
ret = (long)lseek(b->num, 0, 1);
|
||||
break;
|
||||
case BIO_C_SET_FD:
|
||||
fd_free(b);
|
||||
b->num= *((int *)ptr);
|
||||
b->shutdown = (int)num;
|
||||
b->init = 1;
|
||||
break;
|
||||
case BIO_C_GET_FD:
|
||||
if (b->init) {
|
||||
ip = (int *)ptr;
|
||||
if (ip != NULL)
|
||||
*ip = b->num;
|
||||
ret = b->num;
|
||||
} else
|
||||
ret = -1;
|
||||
break;
|
||||
case BIO_CTRL_GET_CLOSE:
|
||||
ret = b->shutdown;
|
||||
break;
|
||||
case BIO_CTRL_SET_CLOSE:
|
||||
b->shutdown = (int)num;
|
||||
break;
|
||||
case BIO_CTRL_PENDING:
|
||||
case BIO_CTRL_WPENDING:
|
||||
ret = 0;
|
||||
break;
|
||||
case BIO_CTRL_DUP:
|
||||
case BIO_CTRL_FLUSH:
|
||||
ret = 1;
|
||||
break;
|
||||
default:
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
fd_puts(BIO *bp, const char *str)
|
||||
{
|
||||
int n, ret;
|
||||
|
||||
n = strlen(str);
|
||||
ret = fd_write(bp, str, n);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
fd_gets(BIO *bp, char *buf, int size)
|
||||
{
|
||||
int ret = 0;
|
||||
char *ptr = buf;
|
||||
char *end = buf + size - 1;
|
||||
|
||||
while ((ptr < end) && (fd_read(bp, ptr, 1) > 0) && (ptr[0] != '\n'))
|
||||
ptr++;
|
||||
|
||||
ptr[0] = '\0';
|
||||
|
||||
if (buf[0] != '\0')
|
||||
ret = strlen(buf);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int
|
||||
BIO_fd_should_retry(int i)
|
||||
{
|
||||
int err;
|
||||
|
||||
if ((i == 0) || (i == -1)) {
|
||||
err = errno;
|
||||
return (BIO_fd_non_fatal_error(err));
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_fd_should_retry);
|
||||
|
||||
int
|
||||
BIO_fd_non_fatal_error(int err)
|
||||
{
|
||||
switch (err) {
|
||||
case ENOTCONN:
|
||||
case EINTR:
|
||||
case EAGAIN:
|
||||
case EINPROGRESS:
|
||||
case EALREADY:
|
||||
return (1);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_fd_non_fatal_error);
|
325
crypto/bio/bss_file.c
Normal file
325
crypto/bio/bss_file.c
Normal file
@@ -0,0 +1,325 @@
|
||||
/* $OpenBSD: bss_file.c,v 1.35 2023/07/05 21:23:37 beck Exp $ */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
/*
|
||||
* 03-Dec-1997 rdenny@dc3.com Fix bug preventing use of stdin/stdout
|
||||
* with binary data (e.g. asn1parse -inform DER < xxx) under
|
||||
* Windows
|
||||
*/
|
||||
|
||||
#ifndef HEADER_BSS_FILE_C
|
||||
#define HEADER_BSS_FILE_C
|
||||
|
||||
#if defined(__linux) || defined(__sun) || defined(__hpux)
|
||||
/* Following definition aliases fopen to fopen64 on above mentioned
|
||||
* platforms. This makes it possible to open and sequentially access
|
||||
* files larger than 2GB from 32-bit application. It does not allow to
|
||||
* traverse them beyond 2GB with fseek/ftell, but on the other hand *no*
|
||||
* 32-bit platform permits that, not with fseek/ftell. Not to mention
|
||||
* that breaking 2GB limit for seeking would require surgery to *our*
|
||||
* API. But sequential access suffices for practical cases when you
|
||||
* can run into large files, such as fingerprinting, so we can let API
|
||||
* alone. For reference, the list of 32-bit platforms which allow for
|
||||
* sequential access of large files without extra "magic" comprise *BSD,
|
||||
* Darwin, IRIX...
|
||||
*/
|
||||
#ifndef _FILE_OFFSET_BITS
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "bio_local.h"
|
||||
|
||||
static int file_write(BIO *h, const char *buf, int num);
|
||||
static int file_read(BIO *h, char *buf, int size);
|
||||
static int file_puts(BIO *h, const char *str);
|
||||
static int file_gets(BIO *h, char *str, int size);
|
||||
static long file_ctrl(BIO *h, int cmd, long arg1, void *arg2);
|
||||
static int file_new(BIO *h);
|
||||
static int file_free(BIO *data);
|
||||
|
||||
static const BIO_METHOD methods_filep = {
|
||||
.type = BIO_TYPE_FILE,
|
||||
.name = "FILE pointer",
|
||||
.bwrite = file_write,
|
||||
.bread = file_read,
|
||||
.bputs = file_puts,
|
||||
.bgets = file_gets,
|
||||
.ctrl = file_ctrl,
|
||||
.create = file_new,
|
||||
.destroy = file_free
|
||||
};
|
||||
|
||||
BIO *
|
||||
BIO_new_file(const char *filename, const char *mode)
|
||||
{
|
||||
BIO *ret;
|
||||
FILE *file = NULL;
|
||||
|
||||
file = fopen(filename, mode);
|
||||
|
||||
if (file == NULL) {
|
||||
SYSerror(errno);
|
||||
ERR_asprintf_error_data("fopen('%s', '%s')", filename, mode);
|
||||
if (errno == ENOENT)
|
||||
BIOerror(BIO_R_NO_SUCH_FILE);
|
||||
else
|
||||
BIOerror(ERR_R_SYS_LIB);
|
||||
return (NULL);
|
||||
}
|
||||
if ((ret = BIO_new(BIO_s_file())) == NULL) {
|
||||
fclose(file);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
BIO_set_fp(ret, file, BIO_CLOSE);
|
||||
return (ret);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_new_file);
|
||||
|
||||
BIO *
|
||||
BIO_new_fp(FILE *stream, int close_flag)
|
||||
{
|
||||
BIO *ret;
|
||||
|
||||
if ((ret = BIO_new(BIO_s_file())) == NULL)
|
||||
return (NULL);
|
||||
|
||||
BIO_set_fp(ret, stream, close_flag);
|
||||
return (ret);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_new_fp);
|
||||
|
||||
const BIO_METHOD *
|
||||
BIO_s_file(void)
|
||||
{
|
||||
return (&methods_filep);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_s_file);
|
||||
|
||||
static int
|
||||
file_new(BIO *bi)
|
||||
{
|
||||
bi->init = 0;
|
||||
bi->num = 0;
|
||||
bi->ptr = NULL;
|
||||
bi->flags=0;
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
file_free(BIO *a)
|
||||
{
|
||||
if (a == NULL)
|
||||
return (0);
|
||||
if (a->shutdown) {
|
||||
if ((a->init) && (a->ptr != NULL)) {
|
||||
fclose (a->ptr);
|
||||
a->ptr = NULL;
|
||||
a->flags = 0;
|
||||
}
|
||||
a->init = 0;
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
file_read(BIO *b, char *out, int outl)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (b->init && out != NULL) {
|
||||
ret = fread(out, 1, outl, (FILE *)b->ptr);
|
||||
if (ret == 0 && ferror((FILE *)b->ptr)) {
|
||||
SYSerror(errno);
|
||||
BIOerror(ERR_R_SYS_LIB);
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
file_write(BIO *b, const char *in, int inl)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (b->init && in != NULL)
|
||||
ret = fwrite(in, 1, inl, (FILE *)b->ptr);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static long
|
||||
file_ctrl(BIO *b, int cmd, long num, void *ptr)
|
||||
{
|
||||
long ret = 1;
|
||||
FILE *fp = (FILE *)b->ptr;
|
||||
FILE **fpp;
|
||||
char p[4];
|
||||
|
||||
switch (cmd) {
|
||||
case BIO_C_FILE_SEEK:
|
||||
case BIO_CTRL_RESET:
|
||||
ret = (long)fseek(fp, num, 0);
|
||||
break;
|
||||
case BIO_CTRL_EOF:
|
||||
ret = (long)feof(fp);
|
||||
break;
|
||||
case BIO_C_FILE_TELL:
|
||||
case BIO_CTRL_INFO:
|
||||
ret = ftell(fp);
|
||||
break;
|
||||
case BIO_C_SET_FILE_PTR:
|
||||
file_free(b);
|
||||
b->shutdown = (int)num&BIO_CLOSE;
|
||||
b->ptr = ptr;
|
||||
b->init = 1;
|
||||
break;
|
||||
case BIO_C_SET_FILENAME:
|
||||
file_free(b);
|
||||
b->shutdown = (int)num&BIO_CLOSE;
|
||||
if (num & BIO_FP_APPEND) {
|
||||
if (num & BIO_FP_READ)
|
||||
strlcpy(p, "a+", sizeof p);
|
||||
else strlcpy(p, "a", sizeof p);
|
||||
} else if ((num & BIO_FP_READ) && (num & BIO_FP_WRITE))
|
||||
strlcpy(p, "r+", sizeof p);
|
||||
else if (num & BIO_FP_WRITE)
|
||||
strlcpy(p, "w", sizeof p);
|
||||
else if (num & BIO_FP_READ)
|
||||
strlcpy(p, "r", sizeof p);
|
||||
else {
|
||||
BIOerror(BIO_R_BAD_FOPEN_MODE);
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
fp = fopen(ptr, p);
|
||||
if (fp == NULL) {
|
||||
SYSerror(errno);
|
||||
ERR_asprintf_error_data("fopen('%s', '%s')", ptr, p);
|
||||
BIOerror(ERR_R_SYS_LIB);
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
b->ptr = fp;
|
||||
b->init = 1;
|
||||
break;
|
||||
case BIO_C_GET_FILE_PTR:
|
||||
/* the ptr parameter is actually a FILE ** in this case. */
|
||||
if (ptr != NULL) {
|
||||
fpp = (FILE **)ptr;
|
||||
*fpp = (FILE *)b->ptr;
|
||||
}
|
||||
break;
|
||||
case BIO_CTRL_GET_CLOSE:
|
||||
ret = (long)b->shutdown;
|
||||
break;
|
||||
case BIO_CTRL_SET_CLOSE:
|
||||
b->shutdown = (int)num;
|
||||
break;
|
||||
case BIO_CTRL_FLUSH:
|
||||
fflush((FILE *)b->ptr);
|
||||
break;
|
||||
case BIO_CTRL_DUP:
|
||||
ret = 1;
|
||||
break;
|
||||
|
||||
case BIO_CTRL_WPENDING:
|
||||
case BIO_CTRL_PENDING:
|
||||
case BIO_CTRL_PUSH:
|
||||
case BIO_CTRL_POP:
|
||||
default:
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
file_gets(BIO *bp, char *buf, int size)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
buf[0] = '\0';
|
||||
if (!fgets(buf, size,(FILE *)bp->ptr))
|
||||
goto err;
|
||||
if (buf[0] != '\0')
|
||||
ret = strlen(buf);
|
||||
err:
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
file_puts(BIO *bp, const char *str)
|
||||
{
|
||||
int n, ret;
|
||||
|
||||
n = strlen(str);
|
||||
ret = file_write(bp, str, n);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
|
||||
#endif /* HEADER_BSS_FILE_C */
|
216
crypto/bio/bss_log.c
Normal file
216
crypto/bio/bss_log.c
Normal file
@@ -0,0 +1,216 @@
|
||||
/* $OpenBSD: bss_log.c,v 1.24 2023/07/05 21:23:37 beck Exp $ */
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1999 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* licensing@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
Why BIO_s_log?
|
||||
|
||||
BIO_s_log is useful for system daemons (or services under NT).
|
||||
It is one-way BIO, it sends all stuff to syslogd (on system that
|
||||
commonly use that), or event log (on NT), or OPCOM (on OpenVMS).
|
||||
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include <openssl/buffer.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "bio_local.h"
|
||||
|
||||
#ifndef NO_SYSLOG
|
||||
|
||||
static int slg_write(BIO *h, const char *buf, int num);
|
||||
static int slg_puts(BIO *h, const char *str);
|
||||
static long slg_ctrl(BIO *h, int cmd, long arg1, void *arg2);
|
||||
static int slg_new(BIO *h);
|
||||
static int slg_free(BIO *data);
|
||||
static void xopenlog(BIO* bp, char* name, int level);
|
||||
static void xsyslog(BIO* bp, int priority, const char* string);
|
||||
static void xcloselog(BIO* bp);
|
||||
|
||||
static const BIO_METHOD methods_slg = {
|
||||
.type = BIO_TYPE_MEM,
|
||||
.name = "syslog",
|
||||
.bwrite = slg_write,
|
||||
.bputs = slg_puts,
|
||||
.ctrl = slg_ctrl,
|
||||
.create = slg_new,
|
||||
.destroy = slg_free
|
||||
};
|
||||
|
||||
const BIO_METHOD *
|
||||
BIO_s_log(void)
|
||||
{
|
||||
return (&methods_slg);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_s_log);
|
||||
|
||||
static int
|
||||
slg_new(BIO *bi)
|
||||
{
|
||||
bi->init = 1;
|
||||
bi->num = 0;
|
||||
bi->ptr = NULL;
|
||||
xopenlog(bi, "application", LOG_DAEMON);
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
slg_free(BIO *a)
|
||||
{
|
||||
if (a == NULL)
|
||||
return (0);
|
||||
xcloselog(a);
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
slg_write(BIO *b, const char *in, int inl)
|
||||
{
|
||||
int ret = inl;
|
||||
char* buf;
|
||||
char* pp;
|
||||
int priority, i;
|
||||
static const struct {
|
||||
int strl;
|
||||
char str[10];
|
||||
int log_level;
|
||||
}
|
||||
mapping[] = {
|
||||
{ 6, "PANIC ", LOG_EMERG },
|
||||
{ 6, "EMERG ", LOG_EMERG },
|
||||
{ 4, "EMR ", LOG_EMERG },
|
||||
{ 6, "ALERT ", LOG_ALERT },
|
||||
{ 4, "ALR ", LOG_ALERT },
|
||||
{ 5, "CRIT ", LOG_CRIT },
|
||||
{ 4, "CRI ", LOG_CRIT },
|
||||
{ 6, "ERROR ", LOG_ERR },
|
||||
{ 4, "ERR ", LOG_ERR },
|
||||
{ 8, "WARNING ", LOG_WARNING },
|
||||
{ 5, "WARN ", LOG_WARNING },
|
||||
{ 4, "WAR ", LOG_WARNING },
|
||||
{ 7, "NOTICE ", LOG_NOTICE },
|
||||
{ 5, "NOTE ", LOG_NOTICE },
|
||||
{ 4, "NOT ", LOG_NOTICE },
|
||||
{ 5, "INFO ", LOG_INFO },
|
||||
{ 4, "INF ", LOG_INFO },
|
||||
{ 6, "DEBUG ", LOG_DEBUG },
|
||||
{ 4, "DBG ", LOG_DEBUG },
|
||||
{ 0, "", LOG_ERR } /* The default */
|
||||
};
|
||||
|
||||
if ((buf = malloc(inl + 1)) == NULL) {
|
||||
return (0);
|
||||
}
|
||||
strlcpy(buf, in, inl + 1);
|
||||
i = 0;
|
||||
while (strncmp(buf, mapping[i].str, mapping[i].strl) != 0)
|
||||
i++;
|
||||
priority = mapping[i].log_level;
|
||||
pp = buf + mapping[i].strl;
|
||||
|
||||
xsyslog(b, priority, pp);
|
||||
|
||||
free(buf);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static long
|
||||
slg_ctrl(BIO *b, int cmd, long num, void *ptr)
|
||||
{
|
||||
switch (cmd) {
|
||||
case BIO_CTRL_SET:
|
||||
xcloselog(b);
|
||||
xopenlog(b, ptr, num);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
slg_puts(BIO *bp, const char *str)
|
||||
{
|
||||
int n, ret;
|
||||
|
||||
n = strlen(str);
|
||||
ret = slg_write(bp, str, n);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
xopenlog(BIO* bp, char* name, int level)
|
||||
{
|
||||
openlog(name, LOG_PID|LOG_CONS, level);
|
||||
}
|
||||
|
||||
static void
|
||||
xsyslog(BIO *bp, int priority, const char *string)
|
||||
{
|
||||
syslog(priority, "%s", string);
|
||||
}
|
||||
|
||||
static void
|
||||
xcloselog(BIO* bp)
|
||||
{
|
||||
closelog();
|
||||
}
|
||||
|
||||
#endif /* NO_SYSLOG */
|
367
crypto/bio/bss_mem.c
Normal file
367
crypto/bio/bss_mem.c
Normal file
@@ -0,0 +1,367 @@
|
||||
/* $OpenBSD: bss_mem.c,v 1.22 2023/07/05 21:23:37 beck Exp $ */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/buffer.h>
|
||||
|
||||
#include "bio_local.h"
|
||||
|
||||
struct bio_mem {
|
||||
BUF_MEM *buf;
|
||||
size_t read_offset;
|
||||
};
|
||||
|
||||
static size_t
|
||||
bio_mem_pending(struct bio_mem *bm)
|
||||
{
|
||||
if (bm->read_offset > bm->buf->length)
|
||||
return 0;
|
||||
|
||||
return bm->buf->length - bm->read_offset;
|
||||
}
|
||||
|
||||
static uint8_t *
|
||||
bio_mem_read_ptr(struct bio_mem *bm)
|
||||
{
|
||||
return &bm->buf->data[bm->read_offset];
|
||||
}
|
||||
|
||||
static int mem_new(BIO *bio);
|
||||
static int mem_free(BIO *bio);
|
||||
static int mem_write(BIO *bio, const char *in, int in_len);
|
||||
static int mem_read(BIO *bio, char *out, int out_len);
|
||||
static int mem_puts(BIO *bio, const char *in);
|
||||
static int mem_gets(BIO *bio, char *out, int out_len);
|
||||
static long mem_ctrl(BIO *bio, int cmd, long arg1, void *arg2);
|
||||
|
||||
static const BIO_METHOD mem_method = {
|
||||
.type = BIO_TYPE_MEM,
|
||||
.name = "memory buffer",
|
||||
.bwrite = mem_write,
|
||||
.bread = mem_read,
|
||||
.bputs = mem_puts,
|
||||
.bgets = mem_gets,
|
||||
.ctrl = mem_ctrl,
|
||||
.create = mem_new,
|
||||
.destroy = mem_free
|
||||
};
|
||||
|
||||
/*
|
||||
* bio->num is used to hold the value to return on 'empty', if it is
|
||||
* 0, should_retry is not set.
|
||||
*/
|
||||
|
||||
const BIO_METHOD *
|
||||
BIO_s_mem(void)
|
||||
{
|
||||
return &mem_method;
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_s_mem);
|
||||
|
||||
BIO *
|
||||
BIO_new_mem_buf(const void *buf, int buf_len)
|
||||
{
|
||||
struct bio_mem *bm;
|
||||
BIO *bio;
|
||||
|
||||
if (buf == NULL) {
|
||||
BIOerror(BIO_R_NULL_PARAMETER);
|
||||
return NULL;
|
||||
}
|
||||
if (buf_len == -1)
|
||||
buf_len = strlen(buf);
|
||||
if (buf_len < 0) {
|
||||
BIOerror(BIO_R_INVALID_ARGUMENT);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((bio = BIO_new(BIO_s_mem())) == NULL)
|
||||
return NULL;
|
||||
|
||||
bm = bio->ptr;
|
||||
bm->buf->data = (void *)buf; /* Trust in the BIO_FLAGS_MEM_RDONLY flag. */
|
||||
bm->buf->length = buf_len;
|
||||
bm->buf->max = buf_len;
|
||||
bio->flags |= BIO_FLAGS_MEM_RDONLY;
|
||||
/* Since this is static data retrying will not help. */
|
||||
bio->num = 0;
|
||||
|
||||
return bio;
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_new_mem_buf);
|
||||
|
||||
static int
|
||||
mem_new(BIO *bio)
|
||||
{
|
||||
struct bio_mem *bm;
|
||||
|
||||
if ((bm = calloc(1, sizeof(*bm))) == NULL)
|
||||
return 0;
|
||||
if ((bm->buf = BUF_MEM_new()) == NULL) {
|
||||
free(bm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bio->shutdown = 1;
|
||||
bio->init = 1;
|
||||
bio->num = -1;
|
||||
bio->ptr = bm;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
mem_free(BIO *bio)
|
||||
{
|
||||
struct bio_mem *bm;
|
||||
|
||||
if (bio == NULL)
|
||||
return 0;
|
||||
if (!bio->init || bio->ptr == NULL)
|
||||
return 1;
|
||||
|
||||
bm = bio->ptr;
|
||||
if (bio->shutdown) {
|
||||
if (bio->flags & BIO_FLAGS_MEM_RDONLY)
|
||||
bm->buf->data = NULL;
|
||||
BUF_MEM_free(bm->buf);
|
||||
}
|
||||
free(bm);
|
||||
bio->ptr = NULL;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
mem_read(BIO *bio, char *out, int out_len)
|
||||
{
|
||||
struct bio_mem *bm = bio->ptr;
|
||||
|
||||
BIO_clear_retry_flags(bio);
|
||||
|
||||
if (out == NULL || out_len <= 0)
|
||||
return 0;
|
||||
|
||||
if ((size_t)out_len > bio_mem_pending(bm))
|
||||
out_len = bio_mem_pending(bm);
|
||||
|
||||
if (out_len == 0) {
|
||||
if (bio->num != 0)
|
||||
BIO_set_retry_read(bio);
|
||||
return bio->num;
|
||||
}
|
||||
|
||||
memcpy(out, bio_mem_read_ptr(bm), out_len);
|
||||
bm->read_offset += out_len;
|
||||
|
||||
return out_len;
|
||||
}
|
||||
|
||||
static int
|
||||
mem_write(BIO *bio, const char *in, int in_len)
|
||||
{
|
||||
struct bio_mem *bm = bio->ptr;
|
||||
size_t buf_len;
|
||||
|
||||
BIO_clear_retry_flags(bio);
|
||||
|
||||
if (in == NULL || in_len <= 0)
|
||||
return 0;
|
||||
|
||||
if (bio->flags & BIO_FLAGS_MEM_RDONLY) {
|
||||
BIOerror(BIO_R_WRITE_TO_READ_ONLY_BIO);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (bm->read_offset > 4096) {
|
||||
memmove(bm->buf->data, bio_mem_read_ptr(bm),
|
||||
bio_mem_pending(bm));
|
||||
bm->buf->length = bio_mem_pending(bm);
|
||||
bm->read_offset = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for overflow and ensure we do not exceed an int, otherwise we
|
||||
* cannot tell if BUF_MEM_grow_clean() succeeded.
|
||||
*/
|
||||
buf_len = bm->buf->length + in_len;
|
||||
if (buf_len < bm->buf->length || buf_len > INT_MAX)
|
||||
return -1;
|
||||
|
||||
if (BUF_MEM_grow_clean(bm->buf, buf_len) != buf_len)
|
||||
return -1;
|
||||
|
||||
memcpy(&bm->buf->data[buf_len - in_len], in, in_len);
|
||||
|
||||
return in_len;
|
||||
}
|
||||
|
||||
static long
|
||||
mem_ctrl(BIO *bio, int cmd, long num, void *ptr)
|
||||
{
|
||||
struct bio_mem *bm = bio->ptr;
|
||||
void **pptr;
|
||||
long ret = 1;
|
||||
|
||||
switch (cmd) {
|
||||
case BIO_CTRL_RESET:
|
||||
if (bm->buf->data != NULL) {
|
||||
if (!(bio->flags & BIO_FLAGS_MEM_RDONLY)) {
|
||||
memset(bm->buf->data, 0, bm->buf->max);
|
||||
bm->buf->length = 0;
|
||||
}
|
||||
bm->read_offset = 0;
|
||||
}
|
||||
break;
|
||||
case BIO_CTRL_EOF:
|
||||
ret = (long)(bio_mem_pending(bm) == 0);
|
||||
break;
|
||||
case BIO_C_SET_BUF_MEM_EOF_RETURN:
|
||||
bio->num = (int)num;
|
||||
break;
|
||||
case BIO_CTRL_INFO:
|
||||
if (ptr != NULL) {
|
||||
pptr = (void **)ptr;
|
||||
*pptr = bio_mem_read_ptr(bm);
|
||||
}
|
||||
ret = (long)bio_mem_pending(bm);
|
||||
break;
|
||||
case BIO_C_SET_BUF_MEM:
|
||||
BUF_MEM_free(bm->buf);
|
||||
bio->shutdown = (int)num;
|
||||
bm->buf = ptr;
|
||||
bm->read_offset = 0;
|
||||
break;
|
||||
case BIO_C_GET_BUF_MEM_PTR:
|
||||
if (ptr != NULL) {
|
||||
pptr = (void **)ptr;
|
||||
*pptr = bm->buf;
|
||||
}
|
||||
break;
|
||||
case BIO_CTRL_GET_CLOSE:
|
||||
ret = (long)bio->shutdown;
|
||||
break;
|
||||
case BIO_CTRL_SET_CLOSE:
|
||||
bio->shutdown = (int)num;
|
||||
break;
|
||||
case BIO_CTRL_WPENDING:
|
||||
ret = 0L;
|
||||
break;
|
||||
case BIO_CTRL_PENDING:
|
||||
ret = (long)bio_mem_pending(bm);
|
||||
break;
|
||||
case BIO_CTRL_DUP:
|
||||
case BIO_CTRL_FLUSH:
|
||||
ret = 1;
|
||||
break;
|
||||
case BIO_CTRL_PUSH:
|
||||
case BIO_CTRL_POP:
|
||||
default:
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
mem_gets(BIO *bio, char *out, int out_len)
|
||||
{
|
||||
struct bio_mem *bm = bio->ptr;
|
||||
int i, out_max;
|
||||
char *p;
|
||||
int ret = -1;
|
||||
|
||||
BIO_clear_retry_flags(bio);
|
||||
|
||||
out_max = bio_mem_pending(bm);
|
||||
if (out_len - 1 < out_max)
|
||||
out_max = out_len - 1;
|
||||
if (out_max <= 0) {
|
||||
*out = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
p = bio_mem_read_ptr(bm);
|
||||
for (i = 0; i < out_max; i++) {
|
||||
if (p[i] == '\n') {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* i is now the max num of bytes to copy, either out_max or up to and
|
||||
* including the first newline
|
||||
*/
|
||||
if ((ret = mem_read(bio, out, i)) > 0)
|
||||
out[ret] = '\0';
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
mem_puts(BIO *bio, const char *in)
|
||||
{
|
||||
return mem_write(bio, in, strlen(in));
|
||||
}
|
161
crypto/bio/bss_null.c
Normal file
161
crypto/bio/bss_null.c
Normal file
@@ -0,0 +1,161 @@
|
||||
/* $OpenBSD: bss_null.c,v 1.13 2023/07/05 21:23:37 beck Exp $ */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/bio.h>
|
||||
|
||||
#include "bio_local.h"
|
||||
|
||||
static int null_write(BIO *h, const char *buf, int num);
|
||||
static int null_read(BIO *h, char *buf, int size);
|
||||
static int null_puts(BIO *h, const char *str);
|
||||
static int null_gets(BIO *h, char *str, int size);
|
||||
static long null_ctrl(BIO *h, int cmd, long arg1, void *arg2);
|
||||
static int null_new(BIO *h);
|
||||
static int null_free(BIO *data);
|
||||
|
||||
static const BIO_METHOD null_method = {
|
||||
.type = BIO_TYPE_NULL,
|
||||
.name = "NULL",
|
||||
.bwrite = null_write,
|
||||
.bread = null_read,
|
||||
.bputs = null_puts,
|
||||
.bgets = null_gets,
|
||||
.ctrl = null_ctrl,
|
||||
.create = null_new,
|
||||
.destroy = null_free
|
||||
};
|
||||
|
||||
const BIO_METHOD *
|
||||
BIO_s_null(void)
|
||||
{
|
||||
return (&null_method);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_s_null);
|
||||
|
||||
static int
|
||||
null_new(BIO *bi)
|
||||
{
|
||||
bi->init = 1;
|
||||
bi->num = 0;
|
||||
bi->ptr = (NULL);
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
null_free(BIO *a)
|
||||
{
|
||||
if (a == NULL)
|
||||
return (0);
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
null_read(BIO *b, char *out, int outl)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
null_write(BIO *b, const char *in, int inl)
|
||||
{
|
||||
return (inl);
|
||||
}
|
||||
|
||||
static long
|
||||
null_ctrl(BIO *b, int cmd, long num, void *ptr)
|
||||
{
|
||||
long ret = 1;
|
||||
|
||||
switch (cmd) {
|
||||
case BIO_CTRL_RESET:
|
||||
case BIO_CTRL_EOF:
|
||||
case BIO_CTRL_SET:
|
||||
case BIO_CTRL_SET_CLOSE:
|
||||
case BIO_CTRL_FLUSH:
|
||||
case BIO_CTRL_DUP:
|
||||
ret = 1;
|
||||
break;
|
||||
case BIO_CTRL_GET_CLOSE:
|
||||
case BIO_CTRL_INFO:
|
||||
case BIO_CTRL_GET:
|
||||
case BIO_CTRL_PENDING:
|
||||
case BIO_CTRL_WPENDING:
|
||||
default:
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
null_gets(BIO *bp, char *buf, int size)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
null_puts(BIO *bp, const char *str)
|
||||
{
|
||||
if (str == NULL)
|
||||
return (0);
|
||||
return (strlen(str));
|
||||
}
|
244
crypto/bio/bss_sock.c
Normal file
244
crypto/bio/bss_sock.c
Normal file
@@ -0,0 +1,244 @@
|
||||
/* $OpenBSD: bss_sock.c,v 1.27 2023/08/07 10:54:14 tb Exp $ */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <openssl/bio.h>
|
||||
|
||||
#include "bio_local.h"
|
||||
|
||||
static int sock_write(BIO *h, const char *buf, int num);
|
||||
static int sock_read(BIO *h, char *buf, int size);
|
||||
static int sock_puts(BIO *h, const char *str);
|
||||
static long sock_ctrl(BIO *h, int cmd, long arg1, void *arg2);
|
||||
static int sock_new(BIO *h);
|
||||
static int sock_free(BIO *data);
|
||||
int BIO_sock_should_retry(int s);
|
||||
|
||||
static const BIO_METHOD methods_sockp = {
|
||||
.type = BIO_TYPE_SOCKET,
|
||||
.name = "socket",
|
||||
.bwrite = sock_write,
|
||||
.bread = sock_read,
|
||||
.bputs = sock_puts,
|
||||
.ctrl = sock_ctrl,
|
||||
.create = sock_new,
|
||||
.destroy = sock_free
|
||||
};
|
||||
|
||||
const BIO_METHOD *
|
||||
BIO_s_socket(void)
|
||||
{
|
||||
return (&methods_sockp);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_s_socket);
|
||||
|
||||
BIO *
|
||||
BIO_new_socket(int fd, int close_flag)
|
||||
{
|
||||
BIO *ret;
|
||||
|
||||
ret = BIO_new(BIO_s_socket());
|
||||
if (ret == NULL)
|
||||
return (NULL);
|
||||
BIO_set_fd(ret, fd, close_flag);
|
||||
return (ret);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_new_socket);
|
||||
|
||||
static int
|
||||
sock_new(BIO *bi)
|
||||
{
|
||||
bi->init = 0;
|
||||
bi->num = 0;
|
||||
bi->ptr = NULL;
|
||||
bi->flags = 0;
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
sock_free(BIO *a)
|
||||
{
|
||||
if (a == NULL)
|
||||
return (0);
|
||||
if (a->shutdown) {
|
||||
if (a->init) {
|
||||
shutdown(a->num, SHUT_RDWR);
|
||||
close(a->num);
|
||||
}
|
||||
a->init = 0;
|
||||
a->flags = 0;
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
sock_read(BIO *b, char *out, int outl)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (out != NULL) {
|
||||
errno = 0;
|
||||
ret = read(b->num, out, outl);
|
||||
BIO_clear_retry_flags(b);
|
||||
if (ret <= 0) {
|
||||
if (BIO_sock_should_retry(ret))
|
||||
BIO_set_retry_read(b);
|
||||
}
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
sock_write(BIO *b, const char *in, int inl)
|
||||
{
|
||||
int ret;
|
||||
|
||||
errno = 0;
|
||||
ret = write(b->num, in, inl);
|
||||
BIO_clear_retry_flags(b);
|
||||
if (ret <= 0) {
|
||||
if (BIO_sock_should_retry(ret))
|
||||
BIO_set_retry_write(b);
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static long
|
||||
sock_ctrl(BIO *b, int cmd, long num, void *ptr)
|
||||
{
|
||||
long ret = 1;
|
||||
int *ip;
|
||||
|
||||
switch (cmd) {
|
||||
case BIO_C_SET_FD:
|
||||
sock_free(b);
|
||||
b->num = *((int *)ptr);
|
||||
b->shutdown = (int)num;
|
||||
b->init = 1;
|
||||
break;
|
||||
case BIO_C_GET_FD:
|
||||
if (b->init) {
|
||||
ip = (int *)ptr;
|
||||
if (ip != NULL)
|
||||
*ip = b->num;
|
||||
ret = b->num;
|
||||
} else
|
||||
ret = -1;
|
||||
break;
|
||||
case BIO_CTRL_GET_CLOSE:
|
||||
ret = b->shutdown;
|
||||
break;
|
||||
case BIO_CTRL_SET_CLOSE:
|
||||
b->shutdown = (int)num;
|
||||
break;
|
||||
case BIO_CTRL_DUP:
|
||||
case BIO_CTRL_FLUSH:
|
||||
ret = 1;
|
||||
break;
|
||||
default:
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
sock_puts(BIO *bp, const char *str)
|
||||
{
|
||||
int n, ret;
|
||||
|
||||
n = strlen(str);
|
||||
ret = sock_write(bp, str, n);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int
|
||||
BIO_sock_should_retry(int i)
|
||||
{
|
||||
int err;
|
||||
|
||||
if ((i == 0) || (i == -1)) {
|
||||
err = errno;
|
||||
return (BIO_sock_non_fatal_error(err));
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_sock_should_retry);
|
||||
|
||||
int
|
||||
BIO_sock_non_fatal_error(int err)
|
||||
{
|
||||
switch (err) {
|
||||
case ENOTCONN:
|
||||
case EINTR:
|
||||
case EAGAIN:
|
||||
case EINPROGRESS:
|
||||
case EALREADY:
|
||||
return (1);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
LCRYPTO_ALIAS(BIO_sock_non_fatal_error);
|
Reference in New Issue
Block a user