mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
Upgrade openssl from 1.1.0e to 1.1.1b, with source code. 4.0.78
This commit is contained in:
parent
8f1c992379
commit
96dbd7bced
1476 changed files with 616554 additions and 4 deletions
902
trunk/3rdparty/openssl-1.1-fit/crypto/bio/b_addr.c
vendored
Normal file
902
trunk/3rdparty/openssl-1.1-fit/crypto/bio/b_addr.c
vendored
Normal file
|
@ -0,0 +1,902 @@
|
|||
/*
|
||||
* Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bio_lcl.h"
|
||||
#include <openssl/crypto.h>
|
||||
|
||||
#ifndef OPENSSL_NO_SOCK
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/buffer.h>
|
||||
#include "internal/thread_once.h"
|
||||
|
||||
CRYPTO_RWLOCK *bio_lookup_lock;
|
||||
static CRYPTO_ONCE bio_lookup_init = CRYPTO_ONCE_STATIC_INIT;
|
||||
|
||||
/*
|
||||
* Throughout this file and bio_lcl.h, the existence of the macro
|
||||
* AI_PASSIVE is used to detect the availability of struct addrinfo,
|
||||
* getnameinfo() and getaddrinfo(). If that macro doesn't exist,
|
||||
* we use our own implementation instead, using gethostbyname,
|
||||
* getservbyname and a few other.
|
||||
*/
|
||||
|
||||
/**********************************************************************
|
||||
*
|
||||
* Address structure
|
||||
*
|
||||
*/
|
||||
|
||||
BIO_ADDR *BIO_ADDR_new(void)
|
||||
{
|
||||
BIO_ADDR *ret = OPENSSL_zalloc(sizeof(*ret));
|
||||
|
||||
if (ret == NULL) {
|
||||
BIOerr(BIO_F_BIO_ADDR_NEW, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret->sa.sa_family = AF_UNSPEC;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void BIO_ADDR_free(BIO_ADDR *ap)
|
||||
{
|
||||
OPENSSL_free(ap);
|
||||
}
|
||||
|
||||
void BIO_ADDR_clear(BIO_ADDR *ap)
|
||||
{
|
||||
memset(ap, 0, sizeof(*ap));
|
||||
ap->sa.sa_family = AF_UNSPEC;
|
||||
}
|
||||
|
||||
/*
|
||||
* BIO_ADDR_make - non-public routine to fill a BIO_ADDR with the contents
|
||||
* of a struct sockaddr.
|
||||
*/
|
||||
int BIO_ADDR_make(BIO_ADDR *ap, const struct sockaddr *sa)
|
||||
{
|
||||
if (sa->sa_family == AF_INET) {
|
||||
memcpy(&(ap->s_in), sa, sizeof(struct sockaddr_in));
|
||||
return 1;
|
||||
}
|
||||
#ifdef AF_INET6
|
||||
if (sa->sa_family == AF_INET6) {
|
||||
memcpy(&(ap->s_in6), sa, sizeof(struct sockaddr_in6));
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
#ifdef AF_UNIX
|
||||
if (sa->sa_family == AF_UNIX) {
|
||||
memcpy(&(ap->s_un), sa, sizeof(struct sockaddr_un));
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int BIO_ADDR_rawmake(BIO_ADDR *ap, int family,
|
||||
const void *where, size_t wherelen,
|
||||
unsigned short port)
|
||||
{
|
||||
#ifdef AF_UNIX
|
||||
if (family == AF_UNIX) {
|
||||
if (wherelen + 1 > sizeof(ap->s_un.sun_path))
|
||||
return 0;
|
||||
memset(&ap->s_un, 0, sizeof(ap->s_un));
|
||||
ap->s_un.sun_family = family;
|
||||
strncpy(ap->s_un.sun_path, where, sizeof(ap->s_un.sun_path) - 1);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
if (family == AF_INET) {
|
||||
if (wherelen != sizeof(struct in_addr))
|
||||
return 0;
|
||||
memset(&ap->s_in, 0, sizeof(ap->s_in));
|
||||
ap->s_in.sin_family = family;
|
||||
ap->s_in.sin_port = port;
|
||||
ap->s_in.sin_addr = *(struct in_addr *)where;
|
||||
return 1;
|
||||
}
|
||||
#ifdef AF_INET6
|
||||
if (family == AF_INET6) {
|
||||
if (wherelen != sizeof(struct in6_addr))
|
||||
return 0;
|
||||
memset(&ap->s_in6, 0, sizeof(ap->s_in6));
|
||||
ap->s_in6.sin6_family = family;
|
||||
ap->s_in6.sin6_port = port;
|
||||
ap->s_in6.sin6_addr = *(struct in6_addr *)where;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int BIO_ADDR_family(const BIO_ADDR *ap)
|
||||
{
|
||||
return ap->sa.sa_family;
|
||||
}
|
||||
|
||||
int BIO_ADDR_rawaddress(const BIO_ADDR *ap, void *p, size_t *l)
|
||||
{
|
||||
size_t len = 0;
|
||||
const void *addrptr = NULL;
|
||||
|
||||
if (ap->sa.sa_family == AF_INET) {
|
||||
len = sizeof(ap->s_in.sin_addr);
|
||||
addrptr = &ap->s_in.sin_addr;
|
||||
}
|
||||
#ifdef AF_INET6
|
||||
else if (ap->sa.sa_family == AF_INET6) {
|
||||
len = sizeof(ap->s_in6.sin6_addr);
|
||||
addrptr = &ap->s_in6.sin6_addr;
|
||||
}
|
||||
#endif
|
||||
#ifdef AF_UNIX
|
||||
else if (ap->sa.sa_family == AF_UNIX) {
|
||||
len = strlen(ap->s_un.sun_path);
|
||||
addrptr = &ap->s_un.sun_path;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (addrptr == NULL)
|
||||
return 0;
|
||||
|
||||
if (p != NULL) {
|
||||
memcpy(p, addrptr, len);
|
||||
}
|
||||
if (l != NULL)
|
||||
*l = len;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned short BIO_ADDR_rawport(const BIO_ADDR *ap)
|
||||
{
|
||||
if (ap->sa.sa_family == AF_INET)
|
||||
return ap->s_in.sin_port;
|
||||
#ifdef AF_INET6
|
||||
if (ap->sa.sa_family == AF_INET6)
|
||||
return ap->s_in6.sin6_port;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-
|
||||
* addr_strings - helper function to get host and service names
|
||||
* @ap: the BIO_ADDR that has the input info
|
||||
* @numeric: 0 if actual names should be returned, 1 if the numeric
|
||||
* representation should be returned.
|
||||
* @hostname: a pointer to a pointer to a memory area to store the
|
||||
* host name or numeric representation. Unused if NULL.
|
||||
* @service: a pointer to a pointer to a memory area to store the
|
||||
* service name or numeric representation. Unused if NULL.
|
||||
*
|
||||
* The return value is 0 on failure, with the error code in the error
|
||||
* stack, and 1 on success.
|
||||
*/
|
||||
static int addr_strings(const BIO_ADDR *ap, int numeric,
|
||||
char **hostname, char **service)
|
||||
{
|
||||
if (BIO_sock_init() != 1)
|
||||
return 0;
|
||||
|
||||
if (1) {
|
||||
#ifdef AI_PASSIVE
|
||||
int ret = 0;
|
||||
char host[NI_MAXHOST] = "", serv[NI_MAXSERV] = "";
|
||||
int flags = 0;
|
||||
|
||||
if (numeric)
|
||||
flags |= NI_NUMERICHOST | NI_NUMERICSERV;
|
||||
|
||||
if ((ret = getnameinfo(BIO_ADDR_sockaddr(ap),
|
||||
BIO_ADDR_sockaddr_size(ap),
|
||||
host, sizeof(host), serv, sizeof(serv),
|
||||
flags)) != 0) {
|
||||
# ifdef EAI_SYSTEM
|
||||
if (ret == EAI_SYSTEM) {
|
||||
SYSerr(SYS_F_GETNAMEINFO, get_last_socket_error());
|
||||
BIOerr(BIO_F_ADDR_STRINGS, ERR_R_SYS_LIB);
|
||||
} else
|
||||
# endif
|
||||
{
|
||||
BIOerr(BIO_F_ADDR_STRINGS, ERR_R_SYS_LIB);
|
||||
ERR_add_error_data(1, gai_strerror(ret));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* VMS getnameinfo() has a bug, it doesn't fill in serv, which
|
||||
* leaves it with whatever garbage that happens to be there.
|
||||
* However, we initialise serv with the empty string (serv[0]
|
||||
* is therefore NUL), so it gets real easy to detect when things
|
||||
* didn't go the way one might expect.
|
||||
*/
|
||||
if (serv[0] == '\0') {
|
||||
BIO_snprintf(serv, sizeof(serv), "%d",
|
||||
ntohs(BIO_ADDR_rawport(ap)));
|
||||
}
|
||||
|
||||
if (hostname != NULL)
|
||||
*hostname = OPENSSL_strdup(host);
|
||||
if (service != NULL)
|
||||
*service = OPENSSL_strdup(serv);
|
||||
} else {
|
||||
#endif
|
||||
if (hostname != NULL)
|
||||
*hostname = OPENSSL_strdup(inet_ntoa(ap->s_in.sin_addr));
|
||||
if (service != NULL) {
|
||||
char serv[6]; /* port is 16 bits => max 5 decimal digits */
|
||||
BIO_snprintf(serv, sizeof(serv), "%d", ntohs(ap->s_in.sin_port));
|
||||
*service = OPENSSL_strdup(serv);
|
||||
}
|
||||
}
|
||||
|
||||
if ((hostname != NULL && *hostname == NULL)
|
||||
|| (service != NULL && *service == NULL)) {
|
||||
if (hostname != NULL) {
|
||||
OPENSSL_free(*hostname);
|
||||
*hostname = NULL;
|
||||
}
|
||||
if (service != NULL) {
|
||||
OPENSSL_free(*service);
|
||||
*service = NULL;
|
||||
}
|
||||
BIOerr(BIO_F_ADDR_STRINGS, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *BIO_ADDR_hostname_string(const BIO_ADDR *ap, int numeric)
|
||||
{
|
||||
char *hostname = NULL;
|
||||
|
||||
if (addr_strings(ap, numeric, &hostname, NULL))
|
||||
return hostname;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *BIO_ADDR_service_string(const BIO_ADDR *ap, int numeric)
|
||||
{
|
||||
char *service = NULL;
|
||||
|
||||
if (addr_strings(ap, numeric, NULL, &service))
|
||||
return service;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *BIO_ADDR_path_string(const BIO_ADDR *ap)
|
||||
{
|
||||
#ifdef AF_UNIX
|
||||
if (ap->sa.sa_family == AF_UNIX)
|
||||
return OPENSSL_strdup(ap->s_un.sun_path);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* BIO_ADDR_sockaddr - non-public routine to return the struct sockaddr
|
||||
* for a given BIO_ADDR. In reality, this is simply a type safe cast.
|
||||
* The returned struct sockaddr is const, so it can't be tampered with.
|
||||
*/
|
||||
const struct sockaddr *BIO_ADDR_sockaddr(const BIO_ADDR *ap)
|
||||
{
|
||||
return &(ap->sa);
|
||||
}
|
||||
|
||||
/*
|
||||
* BIO_ADDR_sockaddr_noconst - non-public function that does the same
|
||||
* as BIO_ADDR_sockaddr, but returns a non-const. USE WITH CARE, as
|
||||
* it allows you to tamper with the data (and thereby the contents
|
||||
* of the input BIO_ADDR).
|
||||
*/
|
||||
struct sockaddr *BIO_ADDR_sockaddr_noconst(BIO_ADDR *ap)
|
||||
{
|
||||
return &(ap->sa);
|
||||
}
|
||||
|
||||
/*
|
||||
* BIO_ADDR_sockaddr_size - non-public function that returns the size
|
||||
* of the struct sockaddr the BIO_ADDR is using. If the protocol family
|
||||
* isn't set or is something other than AF_INET, AF_INET6 or AF_UNIX,
|
||||
* the size of the BIO_ADDR type is returned.
|
||||
*/
|
||||
socklen_t BIO_ADDR_sockaddr_size(const BIO_ADDR *ap)
|
||||
{
|
||||
if (ap->sa.sa_family == AF_INET)
|
||||
return sizeof(ap->s_in);
|
||||
#ifdef AF_INET6
|
||||
if (ap->sa.sa_family == AF_INET6)
|
||||
return sizeof(ap->s_in6);
|
||||
#endif
|
||||
#ifdef AF_UNIX
|
||||
if (ap->sa.sa_family == AF_UNIX)
|
||||
return sizeof(ap->s_un);
|
||||
#endif
|
||||
return sizeof(*ap);
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
*
|
||||
* Address info database
|
||||
*
|
||||
*/
|
||||
|
||||
const BIO_ADDRINFO *BIO_ADDRINFO_next(const BIO_ADDRINFO *bai)
|
||||
{
|
||||
if (bai != NULL)
|
||||
return bai->bai_next;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int BIO_ADDRINFO_family(const BIO_ADDRINFO *bai)
|
||||
{
|
||||
if (bai != NULL)
|
||||
return bai->bai_family;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int BIO_ADDRINFO_socktype(const BIO_ADDRINFO *bai)
|
||||
{
|
||||
if (bai != NULL)
|
||||
return bai->bai_socktype;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int BIO_ADDRINFO_protocol(const BIO_ADDRINFO *bai)
|
||||
{
|
||||
if (bai != NULL) {
|
||||
if (bai->bai_protocol != 0)
|
||||
return bai->bai_protocol;
|
||||
|
||||
#ifdef AF_UNIX
|
||||
if (bai->bai_family == AF_UNIX)
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
switch (bai->bai_socktype) {
|
||||
case SOCK_STREAM:
|
||||
return IPPROTO_TCP;
|
||||
case SOCK_DGRAM:
|
||||
return IPPROTO_UDP;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* BIO_ADDRINFO_sockaddr_size - non-public function that returns the size
|
||||
* of the struct sockaddr inside the BIO_ADDRINFO.
|
||||
*/
|
||||
socklen_t BIO_ADDRINFO_sockaddr_size(const BIO_ADDRINFO *bai)
|
||||
{
|
||||
if (bai != NULL)
|
||||
return bai->bai_addrlen;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* BIO_ADDRINFO_sockaddr - non-public function that returns bai_addr
|
||||
* as the struct sockaddr it is.
|
||||
*/
|
||||
const struct sockaddr *BIO_ADDRINFO_sockaddr(const BIO_ADDRINFO *bai)
|
||||
{
|
||||
if (bai != NULL)
|
||||
return bai->bai_addr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const BIO_ADDR *BIO_ADDRINFO_address(const BIO_ADDRINFO *bai)
|
||||
{
|
||||
if (bai != NULL)
|
||||
return (BIO_ADDR *)bai->bai_addr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void BIO_ADDRINFO_free(BIO_ADDRINFO *bai)
|
||||
{
|
||||
if (bai == NULL)
|
||||
return;
|
||||
|
||||
#ifdef AI_PASSIVE
|
||||
# ifdef AF_UNIX
|
||||
# define _cond bai->bai_family != AF_UNIX
|
||||
# else
|
||||
# define _cond 1
|
||||
# endif
|
||||
if (_cond) {
|
||||
freeaddrinfo(bai);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Free manually when we know that addrinfo_wrap() was used.
|
||||
* See further comment above addrinfo_wrap()
|
||||
*/
|
||||
while (bai != NULL) {
|
||||
BIO_ADDRINFO *next = bai->bai_next;
|
||||
OPENSSL_free(bai->bai_addr);
|
||||
OPENSSL_free(bai);
|
||||
bai = next;
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
*
|
||||
* Service functions
|
||||
*
|
||||
*/
|
||||
|
||||
/*-
|
||||
* The specs in hostserv can take these forms:
|
||||
*
|
||||
* host:service => *host = "host", *service = "service"
|
||||
* host:* => *host = "host", *service = NULL
|
||||
* host: => *host = "host", *service = NULL
|
||||
* :service => *host = NULL, *service = "service"
|
||||
* *:service => *host = NULL, *service = "service"
|
||||
*
|
||||
* in case no : is present in the string, the result depends on
|
||||
* hostserv_prio, as follows:
|
||||
*
|
||||
* when hostserv_prio == BIO_PARSE_PRIO_HOST
|
||||
* host => *host = "host", *service untouched
|
||||
*
|
||||
* when hostserv_prio == BIO_PARSE_PRIO_SERV
|
||||
* service => *host untouched, *service = "service"
|
||||
*
|
||||
*/
|
||||
int BIO_parse_hostserv(const char *hostserv, char **host, char **service,
|
||||
enum BIO_hostserv_priorities hostserv_prio)
|
||||
{
|
||||
const char *h = NULL; size_t hl = 0;
|
||||
const char *p = NULL; size_t pl = 0;
|
||||
|
||||
if (*hostserv == '[') {
|
||||
if ((p = strchr(hostserv, ']')) == NULL)
|
||||
goto spec_err;
|
||||
h = hostserv + 1;
|
||||
hl = p - h;
|
||||
p++;
|
||||
if (*p == '\0')
|
||||
p = NULL;
|
||||
else if (*p != ':')
|
||||
goto spec_err;
|
||||
else {
|
||||
p++;
|
||||
pl = strlen(p);
|
||||
}
|
||||
} else {
|
||||
const char *p2 = strrchr(hostserv, ':');
|
||||
p = strchr(hostserv, ':');
|
||||
|
||||
/*-
|
||||
* Check for more than one colon. There are three possible
|
||||
* interpretations:
|
||||
* 1. IPv6 address with port number, last colon being separator.
|
||||
* 2. IPv6 address only.
|
||||
* 3. IPv6 address only if hostserv_prio == BIO_PARSE_PRIO_HOST,
|
||||
* IPv6 address and port number if hostserv_prio == BIO_PARSE_PRIO_SERV
|
||||
* Because of this ambiguity, we currently choose to make it an
|
||||
* error.
|
||||
*/
|
||||
if (p != p2)
|
||||
goto amb_err;
|
||||
|
||||
if (p != NULL) {
|
||||
h = hostserv;
|
||||
hl = p - h;
|
||||
p++;
|
||||
pl = strlen(p);
|
||||
} else if (hostserv_prio == BIO_PARSE_PRIO_HOST) {
|
||||
h = hostserv;
|
||||
hl = strlen(h);
|
||||
} else {
|
||||
p = hostserv;
|
||||
pl = strlen(p);
|
||||
}
|
||||
}
|
||||
|
||||
if (p != NULL && strchr(p, ':'))
|
||||
goto spec_err;
|
||||
|
||||
if (h != NULL && host != NULL) {
|
||||
if (hl == 0
|
||||
|| (hl == 1 && h[0] == '*')) {
|
||||
*host = NULL;
|
||||
} else {
|
||||
*host = OPENSSL_strndup(h, hl);
|
||||
if (*host == NULL)
|
||||
goto memerr;
|
||||
}
|
||||
}
|
||||
if (p != NULL && service != NULL) {
|
||||
if (pl == 0
|
||||
|| (pl == 1 && p[0] == '*')) {
|
||||
*service = NULL;
|
||||
} else {
|
||||
*service = OPENSSL_strndup(p, pl);
|
||||
if (*service == NULL)
|
||||
goto memerr;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
amb_err:
|
||||
BIOerr(BIO_F_BIO_PARSE_HOSTSERV, BIO_R_AMBIGUOUS_HOST_OR_SERVICE);
|
||||
return 0;
|
||||
spec_err:
|
||||
BIOerr(BIO_F_BIO_PARSE_HOSTSERV, BIO_R_MALFORMED_HOST_OR_SERVICE);
|
||||
return 0;
|
||||
memerr:
|
||||
BIOerr(BIO_F_BIO_PARSE_HOSTSERV, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* addrinfo_wrap is used to build our own addrinfo "chain".
|
||||
* (it has only one entry, so calling it a chain may be a stretch)
|
||||
* It should ONLY be called when getaddrinfo() and friends
|
||||
* aren't available, OR when dealing with a non IP protocol
|
||||
* family, such as AF_UNIX
|
||||
*
|
||||
* the return value is 1 on success, or 0 on failure, which
|
||||
* only happens if a memory allocation error occurred.
|
||||
*/
|
||||
static int addrinfo_wrap(int family, int socktype,
|
||||
const void *where, size_t wherelen,
|
||||
unsigned short port,
|
||||
BIO_ADDRINFO **bai)
|
||||
{
|
||||
if ((*bai = OPENSSL_zalloc(sizeof(**bai))) == NULL) {
|
||||
BIOerr(BIO_F_ADDRINFO_WRAP, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
(*bai)->bai_family = family;
|
||||
(*bai)->bai_socktype = socktype;
|
||||
if (socktype == SOCK_STREAM)
|
||||
(*bai)->bai_protocol = IPPROTO_TCP;
|
||||
if (socktype == SOCK_DGRAM)
|
||||
(*bai)->bai_protocol = IPPROTO_UDP;
|
||||
#ifdef AF_UNIX
|
||||
if (family == AF_UNIX)
|
||||
(*bai)->bai_protocol = 0;
|
||||
#endif
|
||||
{
|
||||
/* Magic: We know that BIO_ADDR_sockaddr_noconst is really
|
||||
just an advanced cast of BIO_ADDR* to struct sockaddr *
|
||||
by the power of union, so while it may seem that we're
|
||||
creating a memory leak here, we are not. It will be
|
||||
all right. */
|
||||
BIO_ADDR *addr = BIO_ADDR_new();
|
||||
if (addr != NULL) {
|
||||
BIO_ADDR_rawmake(addr, family, where, wherelen, port);
|
||||
(*bai)->bai_addr = BIO_ADDR_sockaddr_noconst(addr);
|
||||
}
|
||||
}
|
||||
(*bai)->bai_next = NULL;
|
||||
if ((*bai)->bai_addr == NULL) {
|
||||
BIO_ADDRINFO_free(*bai);
|
||||
*bai = NULL;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
DEFINE_RUN_ONCE_STATIC(do_bio_lookup_init)
|
||||
{
|
||||
if (!OPENSSL_init_crypto(0, NULL))
|
||||
return 0;
|
||||
bio_lookup_lock = CRYPTO_THREAD_lock_new();
|
||||
return bio_lookup_lock != NULL;
|
||||
}
|
||||
|
||||
int BIO_lookup(const char *host, const char *service,
|
||||
enum BIO_lookup_type lookup_type,
|
||||
int family, int socktype, BIO_ADDRINFO **res)
|
||||
{
|
||||
return BIO_lookup_ex(host, service, lookup_type, family, socktype, 0, res);
|
||||
}
|
||||
|
||||
/*-
|
||||
* BIO_lookup_ex - look up the node and service you want to connect to.
|
||||
* @node: the node you want to connect to.
|
||||
* @service: the service you want to connect to.
|
||||
* @lookup_type: declare intent with the result, client or server.
|
||||
* @family: the address family you want to use. Use AF_UNSPEC for any, or
|
||||
* AF_INET, AF_INET6 or AF_UNIX.
|
||||
* @socktype: The socket type you want to use. Can be SOCK_STREAM, SOCK_DGRAM
|
||||
* or 0 for all.
|
||||
* @protocol: The protocol to use, e.g. IPPROTO_TCP or IPPROTO_UDP or 0 for all.
|
||||
* Note that some platforms may not return IPPROTO_SCTP without
|
||||
* explicitly requesting it (i.e. IPPROTO_SCTP may not be returned
|
||||
* with 0 for the protocol)
|
||||
* @res: Storage place for the resulting list of returned addresses
|
||||
*
|
||||
* This will do a lookup of the node and service that you want to connect to.
|
||||
* It returns a linked list of different addresses you can try to connect to.
|
||||
*
|
||||
* When no longer needed you should call BIO_ADDRINFO_free() to free the result.
|
||||
*
|
||||
* The return value is 1 on success or 0 in case of error.
|
||||
*/
|
||||
int BIO_lookup_ex(const char *host, const char *service, int lookup_type,
|
||||
int family, int socktype, int protocol, BIO_ADDRINFO **res)
|
||||
{
|
||||
int ret = 0; /* Assume failure */
|
||||
|
||||
switch(family) {
|
||||
case AF_INET:
|
||||
#ifdef AF_INET6
|
||||
case AF_INET6:
|
||||
#endif
|
||||
#ifdef AF_UNIX
|
||||
case AF_UNIX:
|
||||
#endif
|
||||
#ifdef AF_UNSPEC
|
||||
case AF_UNSPEC:
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
BIOerr(BIO_F_BIO_LOOKUP_EX, BIO_R_UNSUPPORTED_PROTOCOL_FAMILY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef AF_UNIX
|
||||
if (family == AF_UNIX) {
|
||||
if (addrinfo_wrap(family, socktype, host, strlen(host), 0, res))
|
||||
return 1;
|
||||
else
|
||||
BIOerr(BIO_F_BIO_LOOKUP_EX, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (BIO_sock_init() != 1)
|
||||
return 0;
|
||||
|
||||
if (1) {
|
||||
#ifdef AI_PASSIVE
|
||||
int gai_ret = 0;
|
||||
struct addrinfo hints;
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
|
||||
hints.ai_family = family;
|
||||
hints.ai_socktype = socktype;
|
||||
hints.ai_protocol = protocol;
|
||||
|
||||
if (lookup_type == BIO_LOOKUP_SERVER)
|
||||
hints.ai_flags |= AI_PASSIVE;
|
||||
|
||||
/* Note that |res| SHOULD be a 'struct addrinfo **' thanks to
|
||||
* macro magic in bio_lcl.h
|
||||
*/
|
||||
switch ((gai_ret = getaddrinfo(host, service, &hints, res))) {
|
||||
# ifdef EAI_SYSTEM
|
||||
case EAI_SYSTEM:
|
||||
SYSerr(SYS_F_GETADDRINFO, get_last_socket_error());
|
||||
BIOerr(BIO_F_BIO_LOOKUP_EX, ERR_R_SYS_LIB);
|
||||
break;
|
||||
# endif
|
||||
case 0:
|
||||
ret = 1; /* Success */
|
||||
break;
|
||||
default:
|
||||
BIOerr(BIO_F_BIO_LOOKUP_EX, ERR_R_SYS_LIB);
|
||||
ERR_add_error_data(1, gai_strerror(gai_ret));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
#endif
|
||||
const struct hostent *he;
|
||||
/*
|
||||
* Because struct hostent is defined for 32-bit pointers only with
|
||||
* VMS C, we need to make sure that '&he_fallback_address' and
|
||||
* '&he_fallback_addresses' are 32-bit pointers
|
||||
*/
|
||||
#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
|
||||
# pragma pointer_size save
|
||||
# pragma pointer_size 32
|
||||
#endif
|
||||
/* Windows doesn't seem to have in_addr_t */
|
||||
#ifdef OPENSSL_SYS_WINDOWS
|
||||
static uint32_t he_fallback_address;
|
||||
static const char *he_fallback_addresses[] =
|
||||
{ (char *)&he_fallback_address, NULL };
|
||||
#else
|
||||
static in_addr_t he_fallback_address;
|
||||
static const char *he_fallback_addresses[] =
|
||||
{ (char *)&he_fallback_address, NULL };
|
||||
#endif
|
||||
static const struct hostent he_fallback =
|
||||
{ NULL, NULL, AF_INET, sizeof(he_fallback_address),
|
||||
(char **)&he_fallback_addresses };
|
||||
#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
|
||||
# pragma pointer_size restore
|
||||
#endif
|
||||
|
||||
struct servent *se;
|
||||
/* Apparently, on WIN64, s_proto and s_port have traded places... */
|
||||
#ifdef _WIN64
|
||||
struct servent se_fallback = { NULL, NULL, NULL, 0 };
|
||||
#else
|
||||
struct servent se_fallback = { NULL, NULL, 0, NULL };
|
||||
#endif
|
||||
|
||||
if (!RUN_ONCE(&bio_lookup_init, do_bio_lookup_init)) {
|
||||
BIOerr(BIO_F_BIO_LOOKUP_EX, ERR_R_MALLOC_FAILURE);
|
||||
ret = 0;
|
||||
goto err;
|
||||
}
|
||||
|
||||
CRYPTO_THREAD_write_lock(bio_lookup_lock);
|
||||
he_fallback_address = INADDR_ANY;
|
||||
if (host == NULL) {
|
||||
he = &he_fallback;
|
||||
switch(lookup_type) {
|
||||
case BIO_LOOKUP_CLIENT:
|
||||
he_fallback_address = INADDR_LOOPBACK;
|
||||
break;
|
||||
case BIO_LOOKUP_SERVER:
|
||||
he_fallback_address = INADDR_ANY;
|
||||
break;
|
||||
default:
|
||||
/* We forgot to handle a lookup type! */
|
||||
assert("We forgot to handle a lookup type!" == NULL);
|
||||
BIOerr(BIO_F_BIO_LOOKUP_EX, ERR_R_INTERNAL_ERROR);
|
||||
ret = 0;
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
he = gethostbyname(host);
|
||||
|
||||
if (he == NULL) {
|
||||
#ifndef OPENSSL_SYS_WINDOWS
|
||||
/*
|
||||
* This might be misleading, because h_errno is used as if
|
||||
* it was errno. To minimize mixup add 1000. Underlying
|
||||
* reason for this is that hstrerror is declared obsolete,
|
||||
* not to mention that a) h_errno is not always guaranteed
|
||||
* to be meaningless; b) hstrerror can reside in yet another
|
||||
* library, linking for sake of hstrerror is an overkill;
|
||||
* c) this path is not executed on contemporary systems
|
||||
* anyway [above getaddrinfo/gai_strerror is]. We just let
|
||||
* system administrator figure this out...
|
||||
*/
|
||||
# if defined(OPENSSL_SYS_VXWORKS)
|
||||
/* h_errno doesn't exist on VxWorks */
|
||||
SYSerr(SYS_F_GETHOSTBYNAME, 1000 );
|
||||
# else
|
||||
SYSerr(SYS_F_GETHOSTBYNAME, 1000 + h_errno);
|
||||
# endif
|
||||
#else
|
||||
SYSerr(SYS_F_GETHOSTBYNAME, WSAGetLastError());
|
||||
#endif
|
||||
ret = 0;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (service == NULL) {
|
||||
se_fallback.s_port = 0;
|
||||
se_fallback.s_proto = NULL;
|
||||
se = &se_fallback;
|
||||
} else {
|
||||
char *endp = NULL;
|
||||
long portnum = strtol(service, &endp, 10);
|
||||
|
||||
/*
|
||||
* Because struct servent is defined for 32-bit pointers only with
|
||||
* VMS C, we need to make sure that 'proto' is a 32-bit pointer.
|
||||
*/
|
||||
#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
|
||||
# pragma pointer_size save
|
||||
# pragma pointer_size 32
|
||||
#endif
|
||||
char *proto = NULL;
|
||||
#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
|
||||
# pragma pointer_size restore
|
||||
#endif
|
||||
|
||||
switch (socktype) {
|
||||
case SOCK_STREAM:
|
||||
proto = "tcp";
|
||||
break;
|
||||
case SOCK_DGRAM:
|
||||
proto = "udp";
|
||||
break;
|
||||
}
|
||||
|
||||
if (endp != service && *endp == '\0'
|
||||
&& portnum > 0 && portnum < 65536) {
|
||||
se_fallback.s_port = htons((unsigned short)portnum);
|
||||
se_fallback.s_proto = proto;
|
||||
se = &se_fallback;
|
||||
} else if (endp == service) {
|
||||
se = getservbyname(service, proto);
|
||||
|
||||
if (se == NULL) {
|
||||
#ifndef OPENSSL_SYS_WINDOWS
|
||||
SYSerr(SYS_F_GETSERVBYNAME, errno);
|
||||
#else
|
||||
SYSerr(SYS_F_GETSERVBYNAME, WSAGetLastError());
|
||||
#endif
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
BIOerr(BIO_F_BIO_LOOKUP_EX, BIO_R_MALFORMED_HOST_OR_SERVICE);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
*res = NULL;
|
||||
|
||||
{
|
||||
/*
|
||||
* Because hostent::h_addr_list is an array of 32-bit pointers with VMS C,
|
||||
* we must make sure our iterator designates the same element type, hence
|
||||
* the pointer size dance.
|
||||
*/
|
||||
#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
|
||||
# pragma pointer_size save
|
||||
# pragma pointer_size 32
|
||||
#endif
|
||||
char **addrlistp;
|
||||
#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
|
||||
# pragma pointer_size restore
|
||||
#endif
|
||||
size_t addresses;
|
||||
BIO_ADDRINFO *tmp_bai = NULL;
|
||||
|
||||
/* The easiest way to create a linked list from an
|
||||
array is to start from the back */
|
||||
for(addrlistp = he->h_addr_list; *addrlistp != NULL;
|
||||
addrlistp++)
|
||||
;
|
||||
|
||||
for(addresses = addrlistp - he->h_addr_list;
|
||||
addrlistp--, addresses-- > 0; ) {
|
||||
if (!addrinfo_wrap(he->h_addrtype, socktype,
|
||||
*addrlistp, he->h_length,
|
||||
se->s_port, &tmp_bai))
|
||||
goto addrinfo_malloc_err;
|
||||
tmp_bai->bai_next = *res;
|
||||
*res = tmp_bai;
|
||||
continue;
|
||||
addrinfo_malloc_err:
|
||||
BIO_ADDRINFO_free(*res);
|
||||
*res = NULL;
|
||||
BIOerr(BIO_F_BIO_LOOKUP_EX, ERR_R_MALLOC_FAILURE);
|
||||
ret = 0;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
}
|
||||
err:
|
||||
CRYPTO_THREAD_unlock(bio_lookup_lock);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* OPENSSL_NO_SOCK */
|
148
trunk/3rdparty/openssl-1.1-fit/crypto/bio/b_dump.c
vendored
Normal file
148
trunk/3rdparty/openssl-1.1-fit/crypto/bio/b_dump.c
vendored
Normal file
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/*
|
||||
* Stolen from tjh's ssl/ssl_trc.c stuff.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "bio_lcl.h"
|
||||
|
||||
#define DUMP_WIDTH 16
|
||||
#define DUMP_WIDTH_LESS_INDENT(i) (DUMP_WIDTH - ((i - (i > 6 ? 6 : i) + 3) / 4))
|
||||
|
||||
#define SPACE(buf, pos, n) (sizeof(buf) - (pos) > (n))
|
||||
|
||||
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)
|
||||
{
|
||||
int ret = 0;
|
||||
char buf[288 + 1];
|
||||
int i, j, rows, n;
|
||||
unsigned char ch;
|
||||
int dump_width;
|
||||
|
||||
if (indent < 0)
|
||||
indent = 0;
|
||||
else if (indent > 128)
|
||||
indent = 128;
|
||||
|
||||
dump_width = DUMP_WIDTH_LESS_INDENT(indent);
|
||||
rows = len / dump_width;
|
||||
if ((rows * dump_width) < len)
|
||||
rows++;
|
||||
for (i = 0; i < rows; i++) {
|
||||
n = BIO_snprintf(buf, sizeof(buf), "%*s%04x - ", indent, "",
|
||||
i * dump_width);
|
||||
for (j = 0; j < dump_width; j++) {
|
||||
if (SPACE(buf, n, 3)) {
|
||||
if (((i * dump_width) + j) >= len) {
|
||||
strcpy(buf + n, " ");
|
||||
} else {
|
||||
ch = ((unsigned char)*(s + i * dump_width + j)) & 0xff;
|
||||
BIO_snprintf(buf + n, 4, "%02x%c", ch,
|
||||
j == 7 ? '-' : ' ');
|
||||
}
|
||||
n += 3;
|
||||
}
|
||||
}
|
||||
if (SPACE(buf, n, 2)) {
|
||||
strcpy(buf + n, " ");
|
||||
n += 2;
|
||||
}
|
||||
for (j = 0; j < dump_width; j++) {
|
||||
if (((i * dump_width) + j) >= len)
|
||||
break;
|
||||
if (SPACE(buf, n, 1)) {
|
||||
ch = ((unsigned char)*(s + i * dump_width + j)) & 0xff;
|
||||
#ifndef CHARSET_EBCDIC
|
||||
buf[n++] = ((ch >= ' ') && (ch <= '~')) ? ch : '.';
|
||||
#else
|
||||
buf[n++] = ((ch >= os_toascii[' ']) && (ch <= os_toascii['~']))
|
||||
? os_toebcdic[ch]
|
||||
: '.';
|
||||
#endif
|
||||
buf[n] = '\0';
|
||||
}
|
||||
}
|
||||
if (SPACE(buf, n, 1)) {
|
||||
buf[n++] = '\n';
|
||||
buf[n] = '\0';
|
||||
}
|
||||
/*
|
||||
* if this is the last call then update the ddt_dump thing so that we
|
||||
* will move the selection point in the debug window
|
||||
*/
|
||||
ret += cb((void *)buf, n, u);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_STDIO
|
||||
static int write_fp(const void *data, size_t len, void *fp)
|
||||
{
|
||||
return UP_fwrite(data, len, 1, fp);
|
||||
}
|
||||
|
||||
int BIO_dump_fp(FILE *fp, const char *s, int len)
|
||||
{
|
||||
return BIO_dump_cb(write_fp, fp, s, len);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
int BIO_dump_indent(BIO *bp, const char *s, int len, int indent)
|
||||
{
|
||||
return BIO_dump_indent_cb(write_bio, bp, s, len, indent);
|
||||
}
|
||||
|
||||
int BIO_hex_string(BIO *out, int indent, int width, unsigned char *data,
|
||||
int datalen)
|
||||
{
|
||||
int i, j = 0;
|
||||
|
||||
if (datalen < 1)
|
||||
return 1;
|
||||
|
||||
for (i = 0; i < datalen - 1; i++) {
|
||||
if (i && !j)
|
||||
BIO_printf(out, "%*s", indent, "");
|
||||
|
||||
BIO_printf(out, "%02X:", data[i]);
|
||||
|
||||
j = (j + 1) % width;
|
||||
if (!j)
|
||||
BIO_printf(out, "\n");
|
||||
}
|
||||
|
||||
if (i && !j)
|
||||
BIO_printf(out, "%*s", indent, "");
|
||||
BIO_printf(out, "%02X", data[datalen - 1]);
|
||||
return 1;
|
||||
}
|
930
trunk/3rdparty/openssl-1.1-fit/crypto/bio/b_print.c
vendored
Normal file
930
trunk/3rdparty/openssl-1.1-fit/crypto/bio/b_print.c
vendored
Normal file
|
@ -0,0 +1,930 @@
|
|||
/*
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include "internal/ctype.h"
|
||||
#include "internal/numbers.h"
|
||||
#include <openssl/bio.h>
|
||||
|
||||
/*
|
||||
* Copyright Patrick Powell 1995
|
||||
* This code is based on code written by Patrick Powell <papowell@astart.com>
|
||||
* It may be used for any purpose as long as this notice remains intact
|
||||
* on all source code distributions.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_LONG_DOUBLE
|
||||
# define LDOUBLE long double
|
||||
#else
|
||||
# define LDOUBLE double
|
||||
#endif
|
||||
|
||||
static int fmtstr(char **, char **, size_t *, size_t *,
|
||||
const char *, int, int, int);
|
||||
static int fmtint(char **, char **, size_t *, size_t *,
|
||||
int64_t, int, int, int, int);
|
||||
static int fmtfp(char **, char **, size_t *, size_t *,
|
||||
LDOUBLE, int, int, int, int);
|
||||
static int doapr_outch(char **, char **, size_t *, size_t *, int);
|
||||
static int _dopr(char **sbuffer, char **buffer,
|
||||
size_t *maxlen, size_t *retlen, int *truncated,
|
||||
const char *format, va_list args);
|
||||
|
||||
/* format read states */
|
||||
#define DP_S_DEFAULT 0
|
||||
#define DP_S_FLAGS 1
|
||||
#define DP_S_MIN 2
|
||||
#define DP_S_DOT 3
|
||||
#define DP_S_MAX 4
|
||||
#define DP_S_MOD 5
|
||||
#define DP_S_CONV 6
|
||||
#define DP_S_DONE 7
|
||||
|
||||
/* format flags - Bits */
|
||||
/* left-aligned padding */
|
||||
#define DP_F_MINUS (1 << 0)
|
||||
/* print an explicit '+' for a value with positive sign */
|
||||
#define DP_F_PLUS (1 << 1)
|
||||
/* print an explicit ' ' for a value with positive sign */
|
||||
#define DP_F_SPACE (1 << 2)
|
||||
/* print 0/0x prefix for octal/hex and decimal point for floating point */
|
||||
#define DP_F_NUM (1 << 3)
|
||||
/* print leading zeroes */
|
||||
#define DP_F_ZERO (1 << 4)
|
||||
/* print HEX in UPPPERcase */
|
||||
#define DP_F_UP (1 << 5)
|
||||
/* treat value as unsigned */
|
||||
#define DP_F_UNSIGNED (1 << 6)
|
||||
|
||||
/* conversion flags */
|
||||
#define DP_C_SHORT 1
|
||||
#define DP_C_LONG 2
|
||||
#define DP_C_LDOUBLE 3
|
||||
#define DP_C_LLONG 4
|
||||
#define DP_C_SIZE 5
|
||||
|
||||
/* Floating point formats */
|
||||
#define F_FORMAT 0
|
||||
#define E_FORMAT 1
|
||||
#define G_FORMAT 2
|
||||
|
||||
/* some handy macros */
|
||||
#define char_to_int(p) (p - '0')
|
||||
#define OSSL_MAX(p,q) ((p >= q) ? p : q)
|
||||
|
||||
static int
|
||||
_dopr(char **sbuffer,
|
||||
char **buffer,
|
||||
size_t *maxlen,
|
||||
size_t *retlen, int *truncated, const char *format, va_list args)
|
||||
{
|
||||
char ch;
|
||||
int64_t value;
|
||||
LDOUBLE fvalue;
|
||||
char *strvalue;
|
||||
int min;
|
||||
int max;
|
||||
int state;
|
||||
int flags;
|
||||
int cflags;
|
||||
size_t currlen;
|
||||
|
||||
state = DP_S_DEFAULT;
|
||||
flags = currlen = cflags = min = 0;
|
||||
max = -1;
|
||||
ch = *format++;
|
||||
|
||||
while (state != DP_S_DONE) {
|
||||
if (ch == '\0' || (buffer == NULL && currlen >= *maxlen))
|
||||
state = DP_S_DONE;
|
||||
|
||||
switch (state) {
|
||||
case DP_S_DEFAULT:
|
||||
if (ch == '%')
|
||||
state = DP_S_FLAGS;
|
||||
else
|
||||
if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch))
|
||||
return 0;
|
||||
ch = *format++;
|
||||
break;
|
||||
case DP_S_FLAGS:
|
||||
switch (ch) {
|
||||
case '-':
|
||||
flags |= DP_F_MINUS;
|
||||
ch = *format++;
|
||||
break;
|
||||
case '+':
|
||||
flags |= DP_F_PLUS;
|
||||
ch = *format++;
|
||||
break;
|
||||
case ' ':
|
||||
flags |= DP_F_SPACE;
|
||||
ch = *format++;
|
||||
break;
|
||||
case '#':
|
||||
flags |= DP_F_NUM;
|
||||
ch = *format++;
|
||||
break;
|
||||
case '0':
|
||||
flags |= DP_F_ZERO;
|
||||
ch = *format++;
|
||||
break;
|
||||
default:
|
||||
state = DP_S_MIN;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case DP_S_MIN:
|
||||
if (ossl_isdigit(ch)) {
|
||||
min = 10 * min + char_to_int(ch);
|
||||
ch = *format++;
|
||||
} else if (ch == '*') {
|
||||
min = va_arg(args, int);
|
||||
ch = *format++;
|
||||
state = DP_S_DOT;
|
||||
} else
|
||||
state = DP_S_DOT;
|
||||
break;
|
||||
case DP_S_DOT:
|
||||
if (ch == '.') {
|
||||
state = DP_S_MAX;
|
||||
ch = *format++;
|
||||
} else
|
||||
state = DP_S_MOD;
|
||||
break;
|
||||
case DP_S_MAX:
|
||||
if (ossl_isdigit(ch)) {
|
||||
if (max < 0)
|
||||
max = 0;
|
||||
max = 10 * max + char_to_int(ch);
|
||||
ch = *format++;
|
||||
} else if (ch == '*') {
|
||||
max = va_arg(args, int);
|
||||
ch = *format++;
|
||||
state = DP_S_MOD;
|
||||
} else
|
||||
state = DP_S_MOD;
|
||||
break;
|
||||
case DP_S_MOD:
|
||||
switch (ch) {
|
||||
case 'h':
|
||||
cflags = DP_C_SHORT;
|
||||
ch = *format++;
|
||||
break;
|
||||
case 'l':
|
||||
if (*format == 'l') {
|
||||
cflags = DP_C_LLONG;
|
||||
format++;
|
||||
} else
|
||||
cflags = DP_C_LONG;
|
||||
ch = *format++;
|
||||
break;
|
||||
case 'q':
|
||||
case 'j':
|
||||
cflags = DP_C_LLONG;
|
||||
ch = *format++;
|
||||
break;
|
||||
case 'L':
|
||||
cflags = DP_C_LDOUBLE;
|
||||
ch = *format++;
|
||||
break;
|
||||
case 'z':
|
||||
cflags = DP_C_SIZE;
|
||||
ch = *format++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
state = DP_S_CONV;
|
||||
break;
|
||||
case DP_S_CONV:
|
||||
switch (ch) {
|
||||
case 'd':
|
||||
case 'i':
|
||||
switch (cflags) {
|
||||
case DP_C_SHORT:
|
||||
value = (short int)va_arg(args, int);
|
||||
break;
|
||||
case DP_C_LONG:
|
||||
value = va_arg(args, long int);
|
||||
break;
|
||||
case DP_C_LLONG:
|
||||
value = va_arg(args, int64_t);
|
||||
break;
|
||||
case DP_C_SIZE:
|
||||
value = va_arg(args, ossl_ssize_t);
|
||||
break;
|
||||
default:
|
||||
value = va_arg(args, int);
|
||||
break;
|
||||
}
|
||||
if (!fmtint(sbuffer, buffer, &currlen, maxlen, value, 10, min,
|
||||
max, flags))
|
||||
return 0;
|
||||
break;
|
||||
case 'X':
|
||||
flags |= DP_F_UP;
|
||||
/* FALLTHROUGH */
|
||||
case 'x':
|
||||
case 'o':
|
||||
case 'u':
|
||||
flags |= DP_F_UNSIGNED;
|
||||
switch (cflags) {
|
||||
case DP_C_SHORT:
|
||||
value = (unsigned short int)va_arg(args, unsigned int);
|
||||
break;
|
||||
case DP_C_LONG:
|
||||
value = va_arg(args, unsigned long int);
|
||||
break;
|
||||
case DP_C_LLONG:
|
||||
value = va_arg(args, uint64_t);
|
||||
break;
|
||||
case DP_C_SIZE:
|
||||
value = va_arg(args, size_t);
|
||||
break;
|
||||
default:
|
||||
value = va_arg(args, unsigned int);
|
||||
break;
|
||||
}
|
||||
if (!fmtint(sbuffer, buffer, &currlen, maxlen, value,
|
||||
ch == 'o' ? 8 : (ch == 'u' ? 10 : 16),
|
||||
min, max, flags))
|
||||
return 0;
|
||||
break;
|
||||
case 'f':
|
||||
if (cflags == DP_C_LDOUBLE)
|
||||
fvalue = va_arg(args, LDOUBLE);
|
||||
else
|
||||
fvalue = va_arg(args, double);
|
||||
if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max,
|
||||
flags, F_FORMAT))
|
||||
return 0;
|
||||
break;
|
||||
case 'E':
|
||||
flags |= DP_F_UP;
|
||||
/* fall thru */
|
||||
case 'e':
|
||||
if (cflags == DP_C_LDOUBLE)
|
||||
fvalue = va_arg(args, LDOUBLE);
|
||||
else
|
||||
fvalue = va_arg(args, double);
|
||||
if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max,
|
||||
flags, E_FORMAT))
|
||||
return 0;
|
||||
break;
|
||||
case 'G':
|
||||
flags |= DP_F_UP;
|
||||
/* fall thru */
|
||||
case 'g':
|
||||
if (cflags == DP_C_LDOUBLE)
|
||||
fvalue = va_arg(args, LDOUBLE);
|
||||
else
|
||||
fvalue = va_arg(args, double);
|
||||
if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max,
|
||||
flags, G_FORMAT))
|
||||
return 0;
|
||||
break;
|
||||
case 'c':
|
||||
if (!doapr_outch(sbuffer, buffer, &currlen, maxlen,
|
||||
va_arg(args, int)))
|
||||
return 0;
|
||||
break;
|
||||
case 's':
|
||||
strvalue = va_arg(args, char *);
|
||||
if (max < 0) {
|
||||
if (buffer)
|
||||
max = INT_MAX;
|
||||
else
|
||||
max = *maxlen;
|
||||
}
|
||||
if (!fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue,
|
||||
flags, min, max))
|
||||
return 0;
|
||||
break;
|
||||
case 'p':
|
||||
value = (size_t)va_arg(args, void *);
|
||||
if (!fmtint(sbuffer, buffer, &currlen, maxlen,
|
||||
value, 16, min, max, flags | DP_F_NUM))
|
||||
return 0;
|
||||
break;
|
||||
case 'n':
|
||||
{
|
||||
int *num;
|
||||
num = va_arg(args, int *);
|
||||
*num = currlen;
|
||||
}
|
||||
break;
|
||||
case '%':
|
||||
if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch))
|
||||
return 0;
|
||||
break;
|
||||
case 'w':
|
||||
/* not supported yet, treat as next char */
|
||||
ch = *format++;
|
||||
break;
|
||||
default:
|
||||
/* unknown, skip */
|
||||
break;
|
||||
}
|
||||
ch = *format++;
|
||||
state = DP_S_DEFAULT;
|
||||
flags = cflags = min = 0;
|
||||
max = -1;
|
||||
break;
|
||||
case DP_S_DONE:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* We have to truncate if there is no dynamic buffer and we have filled the
|
||||
* static buffer.
|
||||
*/
|
||||
if (buffer == NULL) {
|
||||
*truncated = (currlen > *maxlen - 1);
|
||||
if (*truncated)
|
||||
currlen = *maxlen - 1;
|
||||
}
|
||||
if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0'))
|
||||
return 0;
|
||||
*retlen = currlen - 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
fmtstr(char **sbuffer,
|
||||
char **buffer,
|
||||
size_t *currlen,
|
||||
size_t *maxlen, const char *value, int flags, int min, int max)
|
||||
{
|
||||
int padlen;
|
||||
size_t strln;
|
||||
int cnt = 0;
|
||||
|
||||
if (value == 0)
|
||||
value = "<NULL>";
|
||||
|
||||
strln = OPENSSL_strnlen(value, max < 0 ? SIZE_MAX : (size_t)max);
|
||||
|
||||
padlen = min - strln;
|
||||
if (min < 0 || padlen < 0)
|
||||
padlen = 0;
|
||||
if (max >= 0) {
|
||||
/*
|
||||
* Calculate the maximum output including padding.
|
||||
* Make sure max doesn't overflow into negativity
|
||||
*/
|
||||
if (max < INT_MAX - padlen)
|
||||
max += padlen;
|
||||
else
|
||||
max = INT_MAX;
|
||||
}
|
||||
if (flags & DP_F_MINUS)
|
||||
padlen = -padlen;
|
||||
|
||||
while ((padlen > 0) && (max < 0 || cnt < max)) {
|
||||
if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
|
||||
return 0;
|
||||
--padlen;
|
||||
++cnt;
|
||||
}
|
||||
while (strln > 0 && (max < 0 || cnt < max)) {
|
||||
if (!doapr_outch(sbuffer, buffer, currlen, maxlen, *value++))
|
||||
return 0;
|
||||
--strln;
|
||||
++cnt;
|
||||
}
|
||||
while ((padlen < 0) && (max < 0 || cnt < max)) {
|
||||
if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
|
||||
return 0;
|
||||
++padlen;
|
||||
++cnt;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
fmtint(char **sbuffer,
|
||||
char **buffer,
|
||||
size_t *currlen,
|
||||
size_t *maxlen, int64_t value, int base, int min, int max, int flags)
|
||||
{
|
||||
int signvalue = 0;
|
||||
const char *prefix = "";
|
||||
uint64_t uvalue;
|
||||
char convert[DECIMAL_SIZE(value) + 3];
|
||||
int place = 0;
|
||||
int spadlen = 0;
|
||||
int zpadlen = 0;
|
||||
int caps = 0;
|
||||
|
||||
if (max < 0)
|
||||
max = 0;
|
||||
uvalue = value;
|
||||
if (!(flags & DP_F_UNSIGNED)) {
|
||||
if (value < 0) {
|
||||
signvalue = '-';
|
||||
uvalue = 0 - (uint64_t)value;
|
||||
} else if (flags & DP_F_PLUS)
|
||||
signvalue = '+';
|
||||
else if (flags & DP_F_SPACE)
|
||||
signvalue = ' ';
|
||||
}
|
||||
if (flags & DP_F_NUM) {
|
||||
if (base == 8)
|
||||
prefix = "0";
|
||||
if (base == 16)
|
||||
prefix = "0x";
|
||||
}
|
||||
if (flags & DP_F_UP)
|
||||
caps = 1;
|
||||
do {
|
||||
convert[place++] = (caps ? "0123456789ABCDEF" : "0123456789abcdef")
|
||||
[uvalue % (unsigned)base];
|
||||
uvalue = (uvalue / (unsigned)base);
|
||||
} while (uvalue && (place < (int)sizeof(convert)));
|
||||
if (place == sizeof(convert))
|
||||
place--;
|
||||
convert[place] = 0;
|
||||
|
||||
zpadlen = max - place;
|
||||
spadlen =
|
||||
min - OSSL_MAX(max, place) - (signvalue ? 1 : 0) - strlen(prefix);
|
||||
if (zpadlen < 0)
|
||||
zpadlen = 0;
|
||||
if (spadlen < 0)
|
||||
spadlen = 0;
|
||||
if (flags & DP_F_ZERO) {
|
||||
zpadlen = OSSL_MAX(zpadlen, spadlen);
|
||||
spadlen = 0;
|
||||
}
|
||||
if (flags & DP_F_MINUS)
|
||||
spadlen = -spadlen;
|
||||
|
||||
/* spaces */
|
||||
while (spadlen > 0) {
|
||||
if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
|
||||
return 0;
|
||||
--spadlen;
|
||||
}
|
||||
|
||||
/* sign */
|
||||
if (signvalue)
|
||||
if (!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue))
|
||||
return 0;
|
||||
|
||||
/* prefix */
|
||||
while (*prefix) {
|
||||
if (!doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix))
|
||||
return 0;
|
||||
prefix++;
|
||||
}
|
||||
|
||||
/* zeros */
|
||||
if (zpadlen > 0) {
|
||||
while (zpadlen > 0) {
|
||||
if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0'))
|
||||
return 0;
|
||||
--zpadlen;
|
||||
}
|
||||
}
|
||||
/* digits */
|
||||
while (place > 0) {
|
||||
if (!doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place]))
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* left justified spaces */
|
||||
while (spadlen < 0) {
|
||||
if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
|
||||
return 0;
|
||||
++spadlen;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static LDOUBLE abs_val(LDOUBLE value)
|
||||
{
|
||||
LDOUBLE result = value;
|
||||
if (value < 0)
|
||||
result = -value;
|
||||
return result;
|
||||
}
|
||||
|
||||
static LDOUBLE pow_10(int in_exp)
|
||||
{
|
||||
LDOUBLE result = 1;
|
||||
while (in_exp) {
|
||||
result *= 10;
|
||||
in_exp--;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static long roundv(LDOUBLE value)
|
||||
{
|
||||
long intpart;
|
||||
intpart = (long)value;
|
||||
value = value - intpart;
|
||||
if (value >= 0.5)
|
||||
intpart++;
|
||||
return intpart;
|
||||
}
|
||||
|
||||
static int
|
||||
fmtfp(char **sbuffer,
|
||||
char **buffer,
|
||||
size_t *currlen,
|
||||
size_t *maxlen, LDOUBLE fvalue, int min, int max, int flags, int style)
|
||||
{
|
||||
int signvalue = 0;
|
||||
LDOUBLE ufvalue;
|
||||
LDOUBLE tmpvalue;
|
||||
char iconvert[20];
|
||||
char fconvert[20];
|
||||
char econvert[20];
|
||||
int iplace = 0;
|
||||
int fplace = 0;
|
||||
int eplace = 0;
|
||||
int padlen = 0;
|
||||
int zpadlen = 0;
|
||||
long exp = 0;
|
||||
unsigned long intpart;
|
||||
unsigned long fracpart;
|
||||
unsigned long max10;
|
||||
int realstyle;
|
||||
|
||||
if (max < 0)
|
||||
max = 6;
|
||||
|
||||
if (fvalue < 0)
|
||||
signvalue = '-';
|
||||
else if (flags & DP_F_PLUS)
|
||||
signvalue = '+';
|
||||
else if (flags & DP_F_SPACE)
|
||||
signvalue = ' ';
|
||||
|
||||
/*
|
||||
* G_FORMAT sometimes prints like E_FORMAT and sometimes like F_FORMAT
|
||||
* depending on the number to be printed. Work out which one it is and use
|
||||
* that from here on.
|
||||
*/
|
||||
if (style == G_FORMAT) {
|
||||
if (fvalue == 0.0) {
|
||||
realstyle = F_FORMAT;
|
||||
} else if (fvalue < 0.0001) {
|
||||
realstyle = E_FORMAT;
|
||||
} else if ((max == 0 && fvalue >= 10)
|
||||
|| (max > 0 && fvalue >= pow_10(max))) {
|
||||
realstyle = E_FORMAT;
|
||||
} else {
|
||||
realstyle = F_FORMAT;
|
||||
}
|
||||
} else {
|
||||
realstyle = style;
|
||||
}
|
||||
|
||||
if (style != F_FORMAT) {
|
||||
tmpvalue = fvalue;
|
||||
/* Calculate the exponent */
|
||||
if (fvalue != 0.0) {
|
||||
while (tmpvalue < 1) {
|
||||
tmpvalue *= 10;
|
||||
exp--;
|
||||
}
|
||||
while (tmpvalue > 10) {
|
||||
tmpvalue /= 10;
|
||||
exp++;
|
||||
}
|
||||
}
|
||||
if (style == G_FORMAT) {
|
||||
/*
|
||||
* In G_FORMAT the "precision" represents significant digits. We
|
||||
* always have at least 1 significant digit.
|
||||
*/
|
||||
if (max == 0)
|
||||
max = 1;
|
||||
/* Now convert significant digits to decimal places */
|
||||
if (realstyle == F_FORMAT) {
|
||||
max -= (exp + 1);
|
||||
if (max < 0) {
|
||||
/*
|
||||
* Should not happen. If we're in F_FORMAT then exp < max?
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* In E_FORMAT there is always one significant digit in front
|
||||
* of the decimal point, so:
|
||||
* significant digits == 1 + decimal places
|
||||
*/
|
||||
max--;
|
||||
}
|
||||
}
|
||||
if (realstyle == E_FORMAT)
|
||||
fvalue = tmpvalue;
|
||||
}
|
||||
ufvalue = abs_val(fvalue);
|
||||
if (ufvalue > ULONG_MAX) {
|
||||
/* Number too big */
|
||||
return 0;
|
||||
}
|
||||
intpart = (unsigned long)ufvalue;
|
||||
|
||||
/*
|
||||
* sorry, we only support 9 digits past the decimal because of our
|
||||
* conversion method
|
||||
*/
|
||||
if (max > 9)
|
||||
max = 9;
|
||||
|
||||
/*
|
||||
* we "cheat" by converting the fractional part to integer by multiplying
|
||||
* by a factor of 10
|
||||
*/
|
||||
max10 = roundv(pow_10(max));
|
||||
fracpart = roundv(pow_10(max) * (ufvalue - intpart));
|
||||
|
||||
if (fracpart >= max10) {
|
||||
intpart++;
|
||||
fracpart -= max10;
|
||||
}
|
||||
|
||||
/* convert integer part */
|
||||
do {
|
||||
iconvert[iplace++] = "0123456789"[intpart % 10];
|
||||
intpart = (intpart / 10);
|
||||
} while (intpart && (iplace < (int)sizeof(iconvert)));
|
||||
if (iplace == sizeof(iconvert))
|
||||
iplace--;
|
||||
iconvert[iplace] = 0;
|
||||
|
||||
/* convert fractional part */
|
||||
while (fplace < max) {
|
||||
if (style == G_FORMAT && fplace == 0 && (fracpart % 10) == 0) {
|
||||
/* We strip trailing zeros in G_FORMAT */
|
||||
max--;
|
||||
fracpart = fracpart / 10;
|
||||
if (fplace < max)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
fconvert[fplace++] = "0123456789"[fracpart % 10];
|
||||
fracpart = (fracpart / 10);
|
||||
}
|
||||
|
||||
if (fplace == sizeof(fconvert))
|
||||
fplace--;
|
||||
fconvert[fplace] = 0;
|
||||
|
||||
/* convert exponent part */
|
||||
if (realstyle == E_FORMAT) {
|
||||
int tmpexp;
|
||||
if (exp < 0)
|
||||
tmpexp = -exp;
|
||||
else
|
||||
tmpexp = exp;
|
||||
|
||||
do {
|
||||
econvert[eplace++] = "0123456789"[tmpexp % 10];
|
||||
tmpexp = (tmpexp / 10);
|
||||
} while (tmpexp > 0 && eplace < (int)sizeof(econvert));
|
||||
/* Exponent is huge!! Too big to print */
|
||||
if (tmpexp > 0)
|
||||
return 0;
|
||||
/* Add a leading 0 for single digit exponents */
|
||||
if (eplace == 1)
|
||||
econvert[eplace++] = '0';
|
||||
}
|
||||
|
||||
/*
|
||||
* -1 for decimal point (if we have one, i.e. max > 0),
|
||||
* another -1 if we are printing a sign
|
||||
*/
|
||||
padlen = min - iplace - max - (max > 0 ? 1 : 0) - ((signvalue) ? 1 : 0);
|
||||
/* Take some off for exponent prefix "+e" and exponent */
|
||||
if (realstyle == E_FORMAT)
|
||||
padlen -= 2 + eplace;
|
||||
zpadlen = max - fplace;
|
||||
if (zpadlen < 0)
|
||||
zpadlen = 0;
|
||||
if (padlen < 0)
|
||||
padlen = 0;
|
||||
if (flags & DP_F_MINUS)
|
||||
padlen = -padlen;
|
||||
|
||||
if ((flags & DP_F_ZERO) && (padlen > 0)) {
|
||||
if (signvalue) {
|
||||
if (!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue))
|
||||
return 0;
|
||||
--padlen;
|
||||
signvalue = 0;
|
||||
}
|
||||
while (padlen > 0) {
|
||||
if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0'))
|
||||
return 0;
|
||||
--padlen;
|
||||
}
|
||||
}
|
||||
while (padlen > 0) {
|
||||
if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
|
||||
return 0;
|
||||
--padlen;
|
||||
}
|
||||
if (signvalue && !doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue))
|
||||
return 0;
|
||||
|
||||
while (iplace > 0) {
|
||||
if (!doapr_outch(sbuffer, buffer, currlen, maxlen, iconvert[--iplace]))
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decimal point. This should probably use locale to find the correct
|
||||
* char to print out.
|
||||
*/
|
||||
if (max > 0 || (flags & DP_F_NUM)) {
|
||||
if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '.'))
|
||||
return 0;
|
||||
|
||||
while (fplace > 0) {
|
||||
if (!doapr_outch(sbuffer, buffer, currlen, maxlen,
|
||||
fconvert[--fplace]))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
while (zpadlen > 0) {
|
||||
if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0'))
|
||||
return 0;
|
||||
--zpadlen;
|
||||
}
|
||||
if (realstyle == E_FORMAT) {
|
||||
char ech;
|
||||
|
||||
if ((flags & DP_F_UP) == 0)
|
||||
ech = 'e';
|
||||
else
|
||||
ech = 'E';
|
||||
if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ech))
|
||||
return 0;
|
||||
if (exp < 0) {
|
||||
if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '-'))
|
||||
return 0;
|
||||
} else {
|
||||
if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '+'))
|
||||
return 0;
|
||||
}
|
||||
while (eplace > 0) {
|
||||
if (!doapr_outch(sbuffer, buffer, currlen, maxlen,
|
||||
econvert[--eplace]))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
while (padlen < 0) {
|
||||
if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
|
||||
return 0;
|
||||
++padlen;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define BUFFER_INC 1024
|
||||
|
||||
static int
|
||||
doapr_outch(char **sbuffer,
|
||||
char **buffer, size_t *currlen, size_t *maxlen, int c)
|
||||
{
|
||||
/* If we haven't at least one buffer, someone has done a big booboo */
|
||||
if (!ossl_assert(*sbuffer != NULL || buffer != NULL))
|
||||
return 0;
|
||||
|
||||
/* |currlen| must always be <= |*maxlen| */
|
||||
if (!ossl_assert(*currlen <= *maxlen))
|
||||
return 0;
|
||||
|
||||
if (buffer && *currlen == *maxlen) {
|
||||
if (*maxlen > INT_MAX - BUFFER_INC)
|
||||
return 0;
|
||||
|
||||
*maxlen += BUFFER_INC;
|
||||
if (*buffer == NULL) {
|
||||
if ((*buffer = OPENSSL_malloc(*maxlen)) == NULL) {
|
||||
BIOerr(BIO_F_DOAPR_OUTCH, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
if (*currlen > 0) {
|
||||
if (!ossl_assert(*sbuffer != NULL))
|
||||
return 0;
|
||||
memcpy(*buffer, *sbuffer, *currlen);
|
||||
}
|
||||
*sbuffer = NULL;
|
||||
} else {
|
||||
char *tmpbuf;
|
||||
tmpbuf = OPENSSL_realloc(*buffer, *maxlen);
|
||||
if (tmpbuf == NULL)
|
||||
return 0;
|
||||
*buffer = tmpbuf;
|
||||
}
|
||||
}
|
||||
|
||||
if (*currlen < *maxlen) {
|
||||
if (*sbuffer)
|
||||
(*sbuffer)[(*currlen)++] = (char)c;
|
||||
else
|
||||
(*buffer)[(*currlen)++] = (char)c;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
int BIO_vprintf(BIO *bio, const char *format, va_list args)
|
||||
{
|
||||
int ret;
|
||||
size_t retlen;
|
||||
char hugebuf[1024 * 2]; /* Was previously 10k, which is unreasonable
|
||||
* in small-stack environments, like threads
|
||||
* or DOS programs. */
|
||||
char *hugebufp = hugebuf;
|
||||
size_t hugebufsize = sizeof(hugebuf);
|
||||
char *dynbuf = NULL;
|
||||
int ignored;
|
||||
|
||||
dynbuf = NULL;
|
||||
if (!_dopr(&hugebufp, &dynbuf, &hugebufsize, &retlen, &ignored, format,
|
||||
args)) {
|
||||
OPENSSL_free(dynbuf);
|
||||
return -1;
|
||||
}
|
||||
if (dynbuf) {
|
||||
ret = BIO_write(bio, dynbuf, (int)retlen);
|
||||
OPENSSL_free(dynbuf);
|
||||
} else {
|
||||
ret = BIO_write(bio, hugebuf, (int)retlen);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* As snprintf is not available everywhere, we provide our own
|
||||
* implementation. This function has nothing to do with BIOs, but it's
|
||||
* closely related to BIO_printf, and we need *some* name prefix ... (XXX the
|
||||
* function should be renamed, but to what?)
|
||||
*/
|
||||
int BIO_snprintf(char *buf, size_t n, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
int ret;
|
||||
|
||||
va_start(args, format);
|
||||
|
||||
ret = BIO_vsnprintf(buf, n, format, args);
|
||||
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args)
|
||||
{
|
||||
size_t retlen;
|
||||
int truncated;
|
||||
|
||||
if (!_dopr(&buf, NULL, &n, &retlen, &truncated, format, args))
|
||||
return -1;
|
||||
|
||||
if (truncated)
|
||||
/*
|
||||
* 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.)
|
||||
*/
|
||||
return -1;
|
||||
else
|
||||
return (retlen <= INT_MAX) ? (int)retlen : -1;
|
||||
}
|
369
trunk/3rdparty/openssl-1.1-fit/crypto/bio/b_sock.c
vendored
Normal file
369
trunk/3rdparty/openssl-1.1-fit/crypto/bio/b_sock.c
vendored
Normal file
|
@ -0,0 +1,369 @@
|
|||
/*
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include "bio_lcl.h"
|
||||
#ifndef OPENSSL_NO_SOCK
|
||||
# define SOCKET_PROTOCOL IPPROTO_TCP
|
||||
# ifdef SO_MAXCONN
|
||||
# define MAX_LISTEN SO_MAXCONN
|
||||
# elif defined(SOMAXCONN)
|
||||
# define MAX_LISTEN SOMAXCONN
|
||||
# else
|
||||
# define MAX_LISTEN 32
|
||||
# endif
|
||||
# if defined(OPENSSL_SYS_WINDOWS)
|
||||
static int wsa_init_done = 0;
|
||||
# endif
|
||||
|
||||
# if OPENSSL_API_COMPAT < 0x10100000L
|
||||
int BIO_get_host_ip(const char *str, unsigned char *ip)
|
||||
{
|
||||
BIO_ADDRINFO *res = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (BIO_sock_init() != 1)
|
||||
return 0; /* don't generate another error code here */
|
||||
|
||||
if (BIO_lookup(str, NULL, BIO_LOOKUP_CLIENT, AF_INET, SOCK_STREAM, &res)) {
|
||||
size_t l;
|
||||
|
||||
if (BIO_ADDRINFO_family(res) != AF_INET) {
|
||||
BIOerr(BIO_F_BIO_GET_HOST_IP,
|
||||
BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET);
|
||||
} else if (BIO_ADDR_rawaddress(BIO_ADDRINFO_address(res), NULL, &l)) {
|
||||
/*
|
||||
* Because only AF_INET addresses will reach this far, we can assert
|
||||
* that l should be 4
|
||||
*/
|
||||
if (ossl_assert(l == 4))
|
||||
ret = BIO_ADDR_rawaddress(BIO_ADDRINFO_address(res), ip, &l);
|
||||
}
|
||||
BIO_ADDRINFO_free(res);
|
||||
} else {
|
||||
ERR_add_error_data(2, "host=", str);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int BIO_get_port(const char *str, unsigned short *port_ptr)
|
||||
{
|
||||
BIO_ADDRINFO *res = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (str == NULL) {
|
||||
BIOerr(BIO_F_BIO_GET_PORT, BIO_R_NO_PORT_DEFINED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (BIO_sock_init() != 1)
|
||||
return 0; /* don't generate another error code here */
|
||||
|
||||
if (BIO_lookup(NULL, str, BIO_LOOKUP_CLIENT, AF_INET, SOCK_STREAM, &res)) {
|
||||
if (BIO_ADDRINFO_family(res) != AF_INET) {
|
||||
BIOerr(BIO_F_BIO_GET_PORT,
|
||||
BIO_R_ADDRINFO_ADDR_IS_NOT_AF_INET);
|
||||
} else {
|
||||
*port_ptr = ntohs(BIO_ADDR_rawport(BIO_ADDRINFO_address(res)));
|
||||
ret = 1;
|
||||
}
|
||||
BIO_ADDRINFO_free(res);
|
||||
} else {
|
||||
ERR_add_error_data(2, "host=", str);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
# endif
|
||||
|
||||
int BIO_sock_error(int sock)
|
||||
{
|
||||
int j = 0, i;
|
||||
socklen_t size = sizeof(j);
|
||||
|
||||
/*
|
||||
* Note: under Windows the third parameter is of type (char *) whereas
|
||||
* under other systems it is (void *) if you don't have a cast it will
|
||||
* choke the compiler: if you do have a cast then you can either go for
|
||||
* (char *) or (void *).
|
||||
*/
|
||||
i = getsockopt(sock, SOL_SOCKET, SO_ERROR, (void *)&j, &size);
|
||||
if (i < 0)
|
||||
return get_last_socket_error();
|
||||
else
|
||||
return j;
|
||||
}
|
||||
|
||||
# if OPENSSL_API_COMPAT < 0x10100000L
|
||||
struct hostent *BIO_gethostbyname(const char *name)
|
||||
{
|
||||
/*
|
||||
* Caching gethostbyname() results forever is wrong, so we have to let
|
||||
* the true gethostbyname() worry about this
|
||||
*/
|
||||
return gethostbyname(name);
|
||||
}
|
||||
# endif
|
||||
|
||||
int BIO_sock_init(void)
|
||||
{
|
||||
# ifdef OPENSSL_SYS_WINDOWS
|
||||
static struct WSAData wsa_state;
|
||||
|
||||
if (!wsa_init_done) {
|
||||
int err;
|
||||
|
||||
wsa_init_done = 1;
|
||||
memset(&wsa_state, 0, sizeof(wsa_state));
|
||||
/*
|
||||
* Not making wsa_state available to the rest of the code is formally
|
||||
* wrong. But the structures we use are [believed to be] invariable
|
||||
* among Winsock DLLs, while API availability is [expected to be]
|
||||
* probed at run-time with DSO_global_lookup.
|
||||
*/
|
||||
if (WSAStartup(0x0202, &wsa_state) != 0) {
|
||||
err = WSAGetLastError();
|
||||
SYSerr(SYS_F_WSASTARTUP, err);
|
||||
BIOerr(BIO_F_BIO_SOCK_INIT, BIO_R_WSASTARTUP);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
# endif /* OPENSSL_SYS_WINDOWS */
|
||||
# ifdef WATT32
|
||||
extern int _watt_do_exit;
|
||||
_watt_do_exit = 0; /* don't make sock_init() call exit() */
|
||||
if (sock_init())
|
||||
return -1;
|
||||
# endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void bio_sock_cleanup_int(void)
|
||||
{
|
||||
# ifdef OPENSSL_SYS_WINDOWS
|
||||
if (wsa_init_done) {
|
||||
wsa_init_done = 0;
|
||||
WSACleanup();
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
int BIO_socket_ioctl(int fd, long type, void *arg)
|
||||
{
|
||||
int i;
|
||||
|
||||
# ifdef __DJGPP__
|
||||
i = ioctlsocket(fd, type, (char *)arg);
|
||||
# else
|
||||
# if defined(OPENSSL_SYS_VMS)
|
||||
/*-
|
||||
* 2011-02-18 SMS.
|
||||
* VMS ioctl() can't tolerate a 64-bit "void *arg", but we
|
||||
* observe that all the consumers pass in an "unsigned long *",
|
||||
* so we arrange a local copy with a short pointer, and use
|
||||
* that, instead.
|
||||
*/
|
||||
# if __INITIAL_POINTER_SIZE == 64
|
||||
# define ARG arg_32p
|
||||
# pragma pointer_size save
|
||||
# pragma pointer_size 32
|
||||
unsigned long arg_32;
|
||||
unsigned long *arg_32p;
|
||||
# pragma pointer_size restore
|
||||
arg_32p = &arg_32;
|
||||
arg_32 = *((unsigned long *)arg);
|
||||
# else /* __INITIAL_POINTER_SIZE == 64 */
|
||||
# define ARG arg
|
||||
# endif /* __INITIAL_POINTER_SIZE == 64 [else] */
|
||||
# else /* defined(OPENSSL_SYS_VMS) */
|
||||
# define ARG arg
|
||||
# endif /* defined(OPENSSL_SYS_VMS) [else] */
|
||||
|
||||
i = ioctlsocket(fd, type, ARG);
|
||||
# endif /* __DJGPP__ */
|
||||
if (i < 0)
|
||||
SYSerr(SYS_F_IOCTLSOCKET, get_last_socket_error());
|
||||
return i;
|
||||
}
|
||||
|
||||
# if OPENSSL_API_COMPAT < 0x10100000L
|
||||
int BIO_get_accept_socket(char *host, int bind_mode)
|
||||
{
|
||||
int s = INVALID_SOCKET;
|
||||
char *h = NULL, *p = NULL;
|
||||
BIO_ADDRINFO *res = NULL;
|
||||
|
||||
if (!BIO_parse_hostserv(host, &h, &p, BIO_PARSE_PRIO_SERV))
|
||||
return INVALID_SOCKET;
|
||||
|
||||
if (BIO_sock_init() != 1)
|
||||
return INVALID_SOCKET;
|
||||
|
||||
if (BIO_lookup(h, p, BIO_LOOKUP_SERVER, AF_UNSPEC, SOCK_STREAM, &res) != 0)
|
||||
goto err;
|
||||
|
||||
if ((s = BIO_socket(BIO_ADDRINFO_family(res), BIO_ADDRINFO_socktype(res),
|
||||
BIO_ADDRINFO_protocol(res), 0)) == INVALID_SOCKET) {
|
||||
s = INVALID_SOCKET;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!BIO_listen(s, BIO_ADDRINFO_address(res),
|
||||
bind_mode ? BIO_SOCK_REUSEADDR : 0)) {
|
||||
BIO_closesocket(s);
|
||||
s = INVALID_SOCKET;
|
||||
}
|
||||
|
||||
err:
|
||||
BIO_ADDRINFO_free(res);
|
||||
OPENSSL_free(h);
|
||||
OPENSSL_free(p);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
int BIO_accept(int sock, char **ip_port)
|
||||
{
|
||||
BIO_ADDR res;
|
||||
int ret = -1;
|
||||
|
||||
ret = BIO_accept_ex(sock, &res, 0);
|
||||
if (ret == (int)INVALID_SOCKET) {
|
||||
if (BIO_sock_should_retry(ret)) {
|
||||
ret = -2;
|
||||
goto end;
|
||||
}
|
||||
SYSerr(SYS_F_ACCEPT, get_last_socket_error());
|
||||
BIOerr(BIO_F_BIO_ACCEPT, BIO_R_ACCEPT_ERROR);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (ip_port != NULL) {
|
||||
char *host = BIO_ADDR_hostname_string(&res, 1);
|
||||
char *port = BIO_ADDR_service_string(&res, 1);
|
||||
if (host != NULL && port != NULL)
|
||||
*ip_port = OPENSSL_zalloc(strlen(host) + strlen(port) + 2);
|
||||
else
|
||||
*ip_port = NULL;
|
||||
|
||||
if (*ip_port == NULL) {
|
||||
BIOerr(BIO_F_BIO_ACCEPT, ERR_R_MALLOC_FAILURE);
|
||||
BIO_closesocket(ret);
|
||||
ret = (int)INVALID_SOCKET;
|
||||
} else {
|
||||
strcpy(*ip_port, host);
|
||||
strcat(*ip_port, ":");
|
||||
strcat(*ip_port, port);
|
||||
}
|
||||
OPENSSL_free(host);
|
||||
OPENSSL_free(port);
|
||||
}
|
||||
|
||||
end:
|
||||
return ret;
|
||||
}
|
||||
# endif
|
||||
|
||||
int BIO_set_tcp_ndelay(int s, int on)
|
||||
{
|
||||
int ret = 0;
|
||||
# if defined(TCP_NODELAY) && (defined(IPPROTO_TCP) || defined(SOL_TCP))
|
||||
int opt;
|
||||
|
||||
# ifdef SOL_TCP
|
||||
opt = SOL_TCP;
|
||||
# else
|
||||
# ifdef IPPROTO_TCP
|
||||
opt = IPPROTO_TCP;
|
||||
# endif
|
||||
# endif
|
||||
|
||||
ret = setsockopt(s, opt, TCP_NODELAY, (char *)&on, sizeof(on));
|
||||
# endif
|
||||
return (ret == 0);
|
||||
}
|
||||
|
||||
int BIO_socket_nbio(int s, int mode)
|
||||
{
|
||||
int ret = -1;
|
||||
int l;
|
||||
|
||||
l = mode;
|
||||
# ifdef FIONBIO
|
||||
l = mode;
|
||||
|
||||
ret = BIO_socket_ioctl(s, FIONBIO, &l);
|
||||
# elif defined(F_GETFL) && defined(F_SETFL) && (defined(O_NONBLOCK) || defined(FNDELAY))
|
||||
/* make sure this call always pushes an error level; BIO_socket_ioctl() does so, so we do too. */
|
||||
|
||||
l = fcntl(s, F_GETFL, 0);
|
||||
if (l == -1) {
|
||||
SYSerr(SYS_F_FCNTL, get_last_sys_error());
|
||||
ret = -1;
|
||||
} else {
|
||||
# if defined(O_NONBLOCK)
|
||||
l &= ~O_NONBLOCK;
|
||||
# else
|
||||
l &= ~FNDELAY; /* BSD4.x */
|
||||
# endif
|
||||
if (mode) {
|
||||
# if defined(O_NONBLOCK)
|
||||
l |= O_NONBLOCK;
|
||||
# else
|
||||
l |= FNDELAY; /* BSD4.x */
|
||||
# endif
|
||||
}
|
||||
ret = fcntl(s, F_SETFL, l);
|
||||
|
||||
if (ret < 0) {
|
||||
SYSerr(SYS_F_FCNTL, get_last_sys_error());
|
||||
}
|
||||
}
|
||||
# else
|
||||
/* make sure this call always pushes an error level; BIO_socket_ioctl() does so, so we do too. */
|
||||
BIOerr(BIO_F_BIO_SOCKET_NBIO, ERR_R_PASSED_INVALID_ARGUMENT);
|
||||
# endif
|
||||
|
||||
return (ret == 0);
|
||||
}
|
||||
|
||||
int BIO_sock_info(int sock,
|
||||
enum BIO_sock_info_type type, union BIO_sock_info_u *info)
|
||||
{
|
||||
switch (type) {
|
||||
case BIO_SOCK_INFO_ADDRESS:
|
||||
{
|
||||
socklen_t addr_len;
|
||||
int ret = 0;
|
||||
addr_len = sizeof(*info->addr);
|
||||
ret = getsockname(sock, BIO_ADDR_sockaddr_noconst(info->addr),
|
||||
&addr_len);
|
||||
if (ret == -1) {
|
||||
SYSerr(SYS_F_GETSOCKNAME, get_last_socket_error());
|
||||
BIOerr(BIO_F_BIO_SOCK_INFO, BIO_R_GETSOCKNAME_ERROR);
|
||||
return 0;
|
||||
}
|
||||
if ((size_t)addr_len > sizeof(*info->addr)) {
|
||||
BIOerr(BIO_F_BIO_SOCK_INFO, BIO_R_GETSOCKNAME_TRUNCATED_ADDRESS);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
BIOerr(BIO_F_BIO_SOCK_INFO, BIO_R_UNKNOWN_INFO_TYPE);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
317
trunk/3rdparty/openssl-1.1-fit/crypto/bio/b_sock2.c
vendored
Normal file
317
trunk/3rdparty/openssl-1.1-fit/crypto/bio/b_sock2.c
vendored
Normal file
|
@ -0,0 +1,317 @@
|
|||
/*
|
||||
* Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "bio_lcl.h"
|
||||
|
||||
#include <openssl/err.h>
|
||||
|
||||
#ifndef OPENSSL_NO_SOCK
|
||||
# ifdef SO_MAXCONN
|
||||
# define MAX_LISTEN SO_MAXCONN
|
||||
# elif defined(SOMAXCONN)
|
||||
# define MAX_LISTEN SOMAXCONN
|
||||
# else
|
||||
# define MAX_LISTEN 32
|
||||
# endif
|
||||
|
||||
/*-
|
||||
* BIO_socket - create a socket
|
||||
* @domain: the socket domain (AF_INET, AF_INET6, AF_UNIX, ...)
|
||||
* @socktype: the socket type (SOCK_STEAM, SOCK_DGRAM)
|
||||
* @protocol: the protocol to use (IPPROTO_TCP, IPPROTO_UDP)
|
||||
* @options: BIO socket options (currently unused)
|
||||
*
|
||||
* Creates a socket. This should be called before calling any
|
||||
* of BIO_connect and BIO_listen.
|
||||
*
|
||||
* Returns the file descriptor on success or INVALID_SOCKET on failure. On
|
||||
* failure errno is set, and a status is added to the OpenSSL error stack.
|
||||
*/
|
||||
int BIO_socket(int domain, int socktype, int protocol, int options)
|
||||
{
|
||||
int sock = -1;
|
||||
|
||||
if (BIO_sock_init() != 1)
|
||||
return INVALID_SOCKET;
|
||||
|
||||
sock = socket(domain, socktype, protocol);
|
||||
if (sock == -1) {
|
||||
SYSerr(SYS_F_SOCKET, get_last_socket_error());
|
||||
BIOerr(BIO_F_BIO_SOCKET, BIO_R_UNABLE_TO_CREATE_SOCKET);
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
/*-
|
||||
* BIO_connect - connect to an address
|
||||
* @sock: the socket to connect with
|
||||
* @addr: the address to connect to
|
||||
* @options: BIO socket options
|
||||
*
|
||||
* Connects to the address using the given socket and options.
|
||||
*
|
||||
* Options can be a combination of the following:
|
||||
* - BIO_SOCK_KEEPALIVE: enable regularly sending keep-alive messages.
|
||||
* - BIO_SOCK_NONBLOCK: Make the socket non-blocking.
|
||||
* - BIO_SOCK_NODELAY: don't delay small messages.
|
||||
*
|
||||
* options holds BIO socket options that can be used
|
||||
* You should call this for every address returned by BIO_lookup
|
||||
* until the connection is successful.
|
||||
*
|
||||
* Returns 1 on success or 0 on failure. On failure errno is set
|
||||
* and an error status is added to the OpenSSL error stack.
|
||||
*/
|
||||
int BIO_connect(int sock, const BIO_ADDR *addr, int options)
|
||||
{
|
||||
const int on = 1;
|
||||
|
||||
if (sock == -1) {
|
||||
BIOerr(BIO_F_BIO_CONNECT, BIO_R_INVALID_SOCKET);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!BIO_socket_nbio(sock, (options & BIO_SOCK_NONBLOCK) != 0))
|
||||
return 0;
|
||||
|
||||
if (options & BIO_SOCK_KEEPALIVE) {
|
||||
if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
|
||||
(const void *)&on, sizeof(on)) != 0) {
|
||||
SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error());
|
||||
BIOerr(BIO_F_BIO_CONNECT, BIO_R_UNABLE_TO_KEEPALIVE);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (options & BIO_SOCK_NODELAY) {
|
||||
if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
|
||||
(const void *)&on, sizeof(on)) != 0) {
|
||||
SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error());
|
||||
BIOerr(BIO_F_BIO_CONNECT, BIO_R_UNABLE_TO_NODELAY);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (connect(sock, BIO_ADDR_sockaddr(addr),
|
||||
BIO_ADDR_sockaddr_size(addr)) == -1) {
|
||||
if (!BIO_sock_should_retry(-1)) {
|
||||
SYSerr(SYS_F_CONNECT, get_last_socket_error());
|
||||
BIOerr(BIO_F_BIO_CONNECT, BIO_R_CONNECT_ERROR);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*-
|
||||
* BIO_bind - bind socket to address
|
||||
* @sock: the socket to set
|
||||
* @addr: local address to bind to
|
||||
* @options: BIO socket options
|
||||
*
|
||||
* Binds to the address using the given socket and options.
|
||||
*
|
||||
* Options can be a combination of the following:
|
||||
* - BIO_SOCK_REUSEADDR: Try to reuse the address and port combination
|
||||
* for a recently closed port.
|
||||
*
|
||||
* When restarting the program it could be that the port is still in use. If
|
||||
* you set to BIO_SOCK_REUSEADDR option it will try to reuse the port anyway.
|
||||
* It's recommended that you use this.
|
||||
*/
|
||||
int BIO_bind(int sock, const BIO_ADDR *addr, int options)
|
||||
{
|
||||
# ifndef OPENSSL_SYS_WINDOWS
|
||||
int on = 1;
|
||||
# endif
|
||||
|
||||
if (sock == -1) {
|
||||
BIOerr(BIO_F_BIO_BIND, BIO_R_INVALID_SOCKET);
|
||||
return 0;
|
||||
}
|
||||
|
||||
# ifndef OPENSSL_SYS_WINDOWS
|
||||
/*
|
||||
* SO_REUSEADDR has different behavior on Windows than on
|
||||
* other operating systems, don't set it there.
|
||||
*/
|
||||
if (options & BIO_SOCK_REUSEADDR) {
|
||||
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
|
||||
(const void *)&on, sizeof(on)) != 0) {
|
||||
SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error());
|
||||
BIOerr(BIO_F_BIO_BIND, BIO_R_UNABLE_TO_REUSEADDR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
# endif
|
||||
|
||||
if (bind(sock, BIO_ADDR_sockaddr(addr), BIO_ADDR_sockaddr_size(addr)) != 0) {
|
||||
SYSerr(SYS_F_BIND, get_last_socket_error());
|
||||
BIOerr(BIO_F_BIO_BIND, BIO_R_UNABLE_TO_BIND_SOCKET);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*-
|
||||
* BIO_listen - Creates a listen socket
|
||||
* @sock: the socket to listen with
|
||||
* @addr: local address to bind to
|
||||
* @options: BIO socket options
|
||||
*
|
||||
* Binds to the address using the given socket and options, then
|
||||
* starts listening for incoming connections.
|
||||
*
|
||||
* Options can be a combination of the following:
|
||||
* - BIO_SOCK_KEEPALIVE: enable regularly sending keep-alive messages.
|
||||
* - BIO_SOCK_NONBLOCK: Make the socket non-blocking.
|
||||
* - BIO_SOCK_NODELAY: don't delay small messages.
|
||||
* - BIO_SOCK_REUSEADDR: Try to reuse the address and port combination
|
||||
* for a recently closed port.
|
||||
* - BIO_SOCK_V6_ONLY: When creating an IPv6 socket, make it listen only
|
||||
* for IPv6 addresses and not IPv4 addresses mapped to IPv6.
|
||||
*
|
||||
* It's recommended that you set up both an IPv6 and IPv4 listen socket, and
|
||||
* then check both for new clients that connect to it. You want to set up
|
||||
* the socket as non-blocking in that case since else it could hang.
|
||||
*
|
||||
* Not all operating systems support IPv4 addresses on an IPv6 socket, and for
|
||||
* others it's an option. If you pass the BIO_LISTEN_V6_ONLY it will try to
|
||||
* create the IPv6 sockets to only listen for IPv6 connection.
|
||||
*
|
||||
* It could be that the first BIO_listen() call will listen to all the IPv6
|
||||
* and IPv4 addresses and that then trying to bind to the IPv4 address will
|
||||
* fail. We can't tell the difference between already listening ourself to
|
||||
* it and someone else listening to it when failing and errno is EADDRINUSE, so
|
||||
* it's recommended to not give an error in that case if the first call was
|
||||
* successful.
|
||||
*
|
||||
* When restarting the program it could be that the port is still in use. If
|
||||
* you set to BIO_SOCK_REUSEADDR option it will try to reuse the port anyway.
|
||||
* It's recommended that you use this.
|
||||
*/
|
||||
int BIO_listen(int sock, const BIO_ADDR *addr, int options)
|
||||
{
|
||||
int on = 1;
|
||||
int socktype;
|
||||
socklen_t socktype_len = sizeof(socktype);
|
||||
|
||||
if (sock == -1) {
|
||||
BIOerr(BIO_F_BIO_LISTEN, BIO_R_INVALID_SOCKET);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (getsockopt(sock, SOL_SOCKET, SO_TYPE,
|
||||
(void *)&socktype, &socktype_len) != 0
|
||||
|| socktype_len != sizeof(socktype)) {
|
||||
SYSerr(SYS_F_GETSOCKOPT, get_last_socket_error());
|
||||
BIOerr(BIO_F_BIO_LISTEN, BIO_R_GETTING_SOCKTYPE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!BIO_socket_nbio(sock, (options & BIO_SOCK_NONBLOCK) != 0))
|
||||
return 0;
|
||||
|
||||
if (options & BIO_SOCK_KEEPALIVE) {
|
||||
if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
|
||||
(const void *)&on, sizeof(on)) != 0) {
|
||||
SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error());
|
||||
BIOerr(BIO_F_BIO_LISTEN, BIO_R_UNABLE_TO_KEEPALIVE);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (options & BIO_SOCK_NODELAY) {
|
||||
if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
|
||||
(const void *)&on, sizeof(on)) != 0) {
|
||||
SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error());
|
||||
BIOerr(BIO_F_BIO_LISTEN, BIO_R_UNABLE_TO_NODELAY);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
# ifdef IPV6_V6ONLY
|
||||
if (BIO_ADDR_family(addr) == AF_INET6) {
|
||||
/*
|
||||
* Note: Windows default of IPV6_V6ONLY is ON, and Linux is OFF.
|
||||
* Therefore we always have to use setsockopt here.
|
||||
*/
|
||||
on = options & BIO_SOCK_V6_ONLY ? 1 : 0;
|
||||
if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
|
||||
(const void *)&on, sizeof(on)) != 0) {
|
||||
SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error());
|
||||
BIOerr(BIO_F_BIO_LISTEN, BIO_R_LISTEN_V6_ONLY);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
# endif
|
||||
|
||||
if (!BIO_bind(sock, addr, options))
|
||||
return 0;
|
||||
|
||||
if (socktype != SOCK_DGRAM && listen(sock, MAX_LISTEN) == -1) {
|
||||
SYSerr(SYS_F_LISTEN, get_last_socket_error());
|
||||
BIOerr(BIO_F_BIO_LISTEN, BIO_R_UNABLE_TO_LISTEN_SOCKET);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*-
|
||||
* BIO_accept_ex - Accept new incoming connections
|
||||
* @sock: the listening socket
|
||||
* @addr: the BIO_ADDR to store the peer address in
|
||||
* @options: BIO socket options, applied on the accepted socket.
|
||||
*
|
||||
*/
|
||||
int BIO_accept_ex(int accept_sock, BIO_ADDR *addr_, int options)
|
||||
{
|
||||
socklen_t len;
|
||||
int accepted_sock;
|
||||
BIO_ADDR locaddr;
|
||||
BIO_ADDR *addr = addr_ == NULL ? &locaddr : addr_;
|
||||
|
||||
len = sizeof(*addr);
|
||||
accepted_sock = accept(accept_sock,
|
||||
BIO_ADDR_sockaddr_noconst(addr), &len);
|
||||
if (accepted_sock == -1) {
|
||||
if (!BIO_sock_should_retry(accepted_sock)) {
|
||||
SYSerr(SYS_F_ACCEPT, get_last_socket_error());
|
||||
BIOerr(BIO_F_BIO_ACCEPT_EX, BIO_R_ACCEPT_ERROR);
|
||||
}
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
if (!BIO_socket_nbio(accepted_sock, (options & BIO_SOCK_NONBLOCK) != 0)) {
|
||||
closesocket(accepted_sock);
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
return accepted_sock;
|
||||
}
|
||||
|
||||
/*-
|
||||
* BIO_closesocket - Close a socket
|
||||
* @sock: the socket to close
|
||||
*/
|
||||
int BIO_closesocket(int sock)
|
||||
{
|
||||
if (closesocket(sock) < 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
475
trunk/3rdparty/openssl-1.1-fit/crypto/bio/bf_buff.c
vendored
Normal file
475
trunk/3rdparty/openssl-1.1-fit/crypto/bio/bf_buff.c
vendored
Normal file
|
@ -0,0 +1,475 @@
|
|||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include "bio_lcl.h"
|
||||
#include "internal/cryptlib.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 = {
|
||||
BIO_TYPE_BUFFER,
|
||||
"buffer",
|
||||
/* TODO: Convert to new style write function */
|
||||
bwrite_conv,
|
||||
buffer_write,
|
||||
/* TODO: Convert to new style read function */
|
||||
bread_conv,
|
||||
buffer_read,
|
||||
buffer_puts,
|
||||
buffer_gets,
|
||||
buffer_ctrl,
|
||||
buffer_new,
|
||||
buffer_free,
|
||||
buffer_callback_ctrl,
|
||||
};
|
||||
|
||||
const BIO_METHOD *BIO_f_buffer(void)
|
||||
{
|
||||
return &methods_buffer;
|
||||
}
|
||||
|
||||
static int buffer_new(BIO *bi)
|
||||
{
|
||||
BIO_F_BUFFER_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
|
||||
|
||||
if (ctx == NULL)
|
||||
return 0;
|
||||
ctx->ibuf_size = DEFAULT_BUFFER_SIZE;
|
||||
ctx->ibuf = OPENSSL_malloc(DEFAULT_BUFFER_SIZE);
|
||||
if (ctx->ibuf == NULL) {
|
||||
OPENSSL_free(ctx);
|
||||
return 0;
|
||||
}
|
||||
ctx->obuf_size = DEFAULT_BUFFER_SIZE;
|
||||
ctx->obuf = OPENSSL_malloc(DEFAULT_BUFFER_SIZE);
|
||||
if (ctx->obuf == NULL) {
|
||||
OPENSSL_free(ctx->ibuf);
|
||||
OPENSSL_free(ctx);
|
||||
return 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;
|
||||
OPENSSL_free(b->ibuf);
|
||||
OPENSSL_free(b->obuf);
|
||||
OPENSSL_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_EOF:
|
||||
if (ctx->ibuf_len > 0)
|
||||
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 = OPENSSL_malloc((int)num);
|
||||
if (p1 == NULL)
|
||||
goto malloc_error;
|
||||
OPENSSL_free(ctx->ibuf);
|
||||
ctx->ibuf = p1;
|
||||
}
|
||||
ctx->ibuf_off = 0;
|
||||
ctx->ibuf_len = (int)num;
|
||||
memcpy(ctx->ibuf, ptr, (int)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 = OPENSSL_malloc((int)num);
|
||||
if (p1 == NULL)
|
||||
goto malloc_error;
|
||||
}
|
||||
if ((obs > DEFAULT_BUFFER_SIZE) && (obs != ctx->obuf_size)) {
|
||||
p2 = OPENSSL_malloc((int)num);
|
||||
if (p2 == NULL) {
|
||||
if (p1 != ctx->ibuf)
|
||||
OPENSSL_free(p1);
|
||||
goto malloc_error;
|
||||
}
|
||||
}
|
||||
if (ctx->ibuf != p1) {
|
||||
OPENSSL_free(ctx->ibuf);
|
||||
ctx->ibuf = p1;
|
||||
ctx->ibuf_off = 0;
|
||||
ctx->ibuf_len = 0;
|
||||
ctx->ibuf_size = ibs;
|
||||
}
|
||||
if (ctx->obuf != p2) {
|
||||
OPENSSL_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;
|
||||
case BIO_CTRL_PEEK:
|
||||
/* Ensure there's stuff in the input buffer */
|
||||
{
|
||||
char fake_buf[1];
|
||||
(void)buffer_read(b, fake_buf, 0);
|
||||
}
|
||||
if (num > ctx->ibuf_len)
|
||||
num = ctx->ibuf_len;
|
||||
memcpy(ptr, &(ctx->ibuf[ctx->ibuf_off]), num);
|
||||
ret = num;
|
||||
break;
|
||||
default:
|
||||
if (b->next_bio == NULL)
|
||||
return 0;
|
||||
ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
malloc_error:
|
||||
BIOerr(BIO_F_BUFFER_CTRL, 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));
|
||||
}
|
326
trunk/3rdparty/openssl-1.1-fit/crypto/bio/bf_lbuf.c
vendored
Normal file
326
trunk/3rdparty/openssl-1.1-fit/crypto/bio/bf_lbuf.c
vendored
Normal file
|
@ -0,0 +1,326 @@
|
|||
/*
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include "bio_lcl.h"
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/evp.h>
|
||||
|
||||
static int linebuffer_write(BIO *h, const char *buf, int num);
|
||||
static int linebuffer_read(BIO *h, char *buf, int size);
|
||||
static int linebuffer_puts(BIO *h, const char *str);
|
||||
static int linebuffer_gets(BIO *h, char *str, int size);
|
||||
static long linebuffer_ctrl(BIO *h, int cmd, long arg1, void *arg2);
|
||||
static int linebuffer_new(BIO *h);
|
||||
static int linebuffer_free(BIO *data);
|
||||
static long linebuffer_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp);
|
||||
|
||||
/* A 10k maximum should be enough for most purposes */
|
||||
#define DEFAULT_LINEBUFFER_SIZE 1024*10
|
||||
|
||||
/* #define DEBUG */
|
||||
|
||||
static const BIO_METHOD methods_linebuffer = {
|
||||
BIO_TYPE_LINEBUFFER,
|
||||
"linebuffer",
|
||||
/* TODO: Convert to new style write function */
|
||||
bwrite_conv,
|
||||
linebuffer_write,
|
||||
/* TODO: Convert to new style read function */
|
||||
bread_conv,
|
||||
linebuffer_read,
|
||||
linebuffer_puts,
|
||||
linebuffer_gets,
|
||||
linebuffer_ctrl,
|
||||
linebuffer_new,
|
||||
linebuffer_free,
|
||||
linebuffer_callback_ctrl,
|
||||
};
|
||||
|
||||
const BIO_METHOD *BIO_f_linebuffer(void)
|
||||
{
|
||||
return &methods_linebuffer;
|
||||
}
|
||||
|
||||
typedef struct bio_linebuffer_ctx_struct {
|
||||
char *obuf; /* the output char array */
|
||||
int obuf_size; /* how big is the output buffer */
|
||||
int obuf_len; /* how many bytes are in it */
|
||||
} BIO_LINEBUFFER_CTX;
|
||||
|
||||
static int linebuffer_new(BIO *bi)
|
||||
{
|
||||
BIO_LINEBUFFER_CTX *ctx;
|
||||
|
||||
if ((ctx = OPENSSL_malloc(sizeof(*ctx))) == NULL) {
|
||||
BIOerr(BIO_F_LINEBUFFER_NEW, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
ctx->obuf = OPENSSL_malloc(DEFAULT_LINEBUFFER_SIZE);
|
||||
if (ctx->obuf == NULL) {
|
||||
BIOerr(BIO_F_LINEBUFFER_NEW, ERR_R_MALLOC_FAILURE);
|
||||
OPENSSL_free(ctx);
|
||||
return 0;
|
||||
}
|
||||
ctx->obuf_size = DEFAULT_LINEBUFFER_SIZE;
|
||||
ctx->obuf_len = 0;
|
||||
|
||||
bi->init = 1;
|
||||
bi->ptr = (char *)ctx;
|
||||
bi->flags = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int linebuffer_free(BIO *a)
|
||||
{
|
||||
BIO_LINEBUFFER_CTX *b;
|
||||
|
||||
if (a == NULL)
|
||||
return 0;
|
||||
b = (BIO_LINEBUFFER_CTX *)a->ptr;
|
||||
OPENSSL_free(b->obuf);
|
||||
OPENSSL_free(a->ptr);
|
||||
a->ptr = NULL;
|
||||
a->init = 0;
|
||||
a->flags = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int linebuffer_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 linebuffer_write(BIO *b, const char *in, int inl)
|
||||
{
|
||||
int i, num = 0, foundnl;
|
||||
BIO_LINEBUFFER_CTX *ctx;
|
||||
|
||||
if ((in == NULL) || (inl <= 0))
|
||||
return 0;
|
||||
ctx = (BIO_LINEBUFFER_CTX *)b->ptr;
|
||||
if ((ctx == NULL) || (b->next_bio == NULL))
|
||||
return 0;
|
||||
|
||||
BIO_clear_retry_flags(b);
|
||||
|
||||
do {
|
||||
const char *p;
|
||||
char c;
|
||||
|
||||
for (p = in, c = '\0'; p < in + inl && (c = *p) != '\n'; p++) ;
|
||||
if (c == '\n') {
|
||||
p++;
|
||||
foundnl = 1;
|
||||
} else
|
||||
foundnl = 0;
|
||||
|
||||
/*
|
||||
* If a NL was found and we already have text in the save buffer,
|
||||
* concatenate them and write
|
||||
*/
|
||||
while ((foundnl || p - in > ctx->obuf_size - ctx->obuf_len)
|
||||
&& ctx->obuf_len > 0) {
|
||||
int orig_olen = ctx->obuf_len;
|
||||
|
||||
i = ctx->obuf_size - ctx->obuf_len;
|
||||
if (p - in > 0) {
|
||||
if (i >= p - in) {
|
||||
memcpy(&(ctx->obuf[ctx->obuf_len]), in, p - in);
|
||||
ctx->obuf_len += p - in;
|
||||
inl -= p - in;
|
||||
num += p - in;
|
||||
in = p;
|
||||
} else {
|
||||
memcpy(&(ctx->obuf[ctx->obuf_len]), in, i);
|
||||
ctx->obuf_len += i;
|
||||
inl -= i;
|
||||
in += i;
|
||||
num += i;
|
||||
}
|
||||
}
|
||||
i = BIO_write(b->next_bio, ctx->obuf, ctx->obuf_len);
|
||||
if (i <= 0) {
|
||||
ctx->obuf_len = orig_olen;
|
||||
BIO_copy_next_retry(b);
|
||||
|
||||
if (i < 0)
|
||||
return ((num > 0) ? num : i);
|
||||
if (i == 0)
|
||||
return num;
|
||||
}
|
||||
if (i < ctx->obuf_len)
|
||||
memmove(ctx->obuf, ctx->obuf + i, ctx->obuf_len - i);
|
||||
ctx->obuf_len -= i;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now that the save buffer is emptied, let's write the input buffer
|
||||
* if a NL was found and there is anything to write.
|
||||
*/
|
||||
if ((foundnl || p - in > ctx->obuf_size) && p - in > 0) {
|
||||
i = BIO_write(b->next_bio, in, p - in);
|
||||
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;
|
||||
}
|
||||
}
|
||||
while (foundnl && inl > 0);
|
||||
/*
|
||||
* We've written as much as we can. The rest of the input buffer, if
|
||||
* any, is text that doesn't and with a NL and therefore needs to be
|
||||
* saved for the next trip.
|
||||
*/
|
||||
if (inl > 0) {
|
||||
memcpy(&(ctx->obuf[ctx->obuf_len]), in, inl);
|
||||
ctx->obuf_len += inl;
|
||||
num += inl;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
static long linebuffer_ctrl(BIO *b, int cmd, long num, void *ptr)
|
||||
{
|
||||
BIO *dbio;
|
||||
BIO_LINEBUFFER_CTX *ctx;
|
||||
long ret = 1;
|
||||
char *p;
|
||||
int r;
|
||||
int obs;
|
||||
|
||||
ctx = (BIO_LINEBUFFER_CTX *)b->ptr;
|
||||
|
||||
switch (cmd) {
|
||||
case BIO_CTRL_RESET:
|
||||
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_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_C_SET_BUFF_SIZE:
|
||||
obs = (int)num;
|
||||
p = ctx->obuf;
|
||||
if ((obs > DEFAULT_LINEBUFFER_SIZE) && (obs != ctx->obuf_size)) {
|
||||
p = OPENSSL_malloc((int)num);
|
||||
if (p == NULL)
|
||||
goto malloc_error;
|
||||
}
|
||||
if (ctx->obuf != p) {
|
||||
if (ctx->obuf_len > obs) {
|
||||
ctx->obuf_len = obs;
|
||||
}
|
||||
memcpy(p, ctx->obuf, ctx->obuf_len);
|
||||
OPENSSL_free(ctx->obuf);
|
||||
ctx->obuf = p;
|
||||
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_len);
|
||||
BIO_copy_next_retry(b);
|
||||
if (r <= 0)
|
||||
return (long)r;
|
||||
if (r < ctx->obuf_len)
|
||||
memmove(ctx->obuf, ctx->obuf + r, ctx->obuf_len - r);
|
||||
ctx->obuf_len -= r;
|
||||
} else {
|
||||
ctx->obuf_len = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
|
||||
break;
|
||||
case BIO_CTRL_DUP:
|
||||
dbio = (BIO *)ptr;
|
||||
if (!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:
|
||||
BIOerr(BIO_F_LINEBUFFER_CTRL, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long linebuffer_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 linebuffer_gets(BIO *b, char *buf, int size)
|
||||
{
|
||||
if (b->next_bio == NULL)
|
||||
return 0;
|
||||
return BIO_gets(b->next_bio, buf, size);
|
||||
}
|
||||
|
||||
static int linebuffer_puts(BIO *b, const char *str)
|
||||
{
|
||||
return linebuffer_write(b, str, strlen(str));
|
||||
}
|
200
trunk/3rdparty/openssl-1.1-fit/crypto/bio/bf_nbio.c
vendored
Normal file
200
trunk/3rdparty/openssl-1.1-fit/crypto/bio/bf_nbio.c
vendored
Normal file
|
@ -0,0 +1,200 @@
|
|||
/*
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include "bio_lcl.h"
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/rand.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 = {
|
||||
BIO_TYPE_NBIO_TEST,
|
||||
"non-blocking IO test filter",
|
||||
/* TODO: Convert to new style write function */
|
||||
bwrite_conv,
|
||||
nbiof_write,
|
||||
/* TODO: Convert to new style read function */
|
||||
bread_conv,
|
||||
nbiof_read,
|
||||
nbiof_puts,
|
||||
nbiof_gets,
|
||||
nbiof_ctrl,
|
||||
nbiof_new,
|
||||
nbiof_free,
|
||||
nbiof_callback_ctrl,
|
||||
};
|
||||
|
||||
const BIO_METHOD *BIO_f_nbio_test(void)
|
||||
{
|
||||
return &methods_nbiof;
|
||||
}
|
||||
|
||||
static int nbiof_new(BIO *bi)
|
||||
{
|
||||
NBIO_TEST *nt;
|
||||
|
||||
if ((nt = OPENSSL_zalloc(sizeof(*nt))) == NULL) {
|
||||
BIOerr(BIO_F_NBIOF_NEW, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
nt->lrn = -1;
|
||||
nt->lwn = -1;
|
||||
bi->ptr = (char *)nt;
|
||||
bi->init = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int nbiof_free(BIO *a)
|
||||
{
|
||||
if (a == NULL)
|
||||
return 0;
|
||||
OPENSSL_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);
|
||||
if (RAND_priv_bytes(&n, 1) <= 0)
|
||||
return -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 {
|
||||
if (RAND_priv_bytes(&n, 1) <= 0)
|
||||
return -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);
|
||||
}
|
122
trunk/3rdparty/openssl-1.1-fit/crypto/bio/bf_null.c
vendored
Normal file
122
trunk/3rdparty/openssl-1.1-fit/crypto/bio/bf_null.c
vendored
Normal file
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include "bio_lcl.h"
|
||||
#include "internal/cryptlib.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 long nullf_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp);
|
||||
static const BIO_METHOD methods_nullf = {
|
||||
BIO_TYPE_NULL_FILTER,
|
||||
"NULL filter",
|
||||
/* TODO: Convert to new style write function */
|
||||
bwrite_conv,
|
||||
nullf_write,
|
||||
/* TODO: Convert to new style read function */
|
||||
bread_conv,
|
||||
nullf_read,
|
||||
nullf_puts,
|
||||
nullf_gets,
|
||||
nullf_ctrl,
|
||||
NULL,
|
||||
NULL,
|
||||
nullf_callback_ctrl,
|
||||
};
|
||||
|
||||
const BIO_METHOD *BIO_f_null(void)
|
||||
{
|
||||
return &methods_nullf;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
98
trunk/3rdparty/openssl-1.1-fit/crypto/bio/bio_cb.c
vendored
Normal file
98
trunk/3rdparty/openssl-1.1-fit/crypto/bio/bio_cb.c
vendored
Normal file
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "bio_lcl.h"
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/err.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;
|
||||
long r = 1;
|
||||
int len, left;
|
||||
|
||||
if (BIO_CB_RETURN & cmd)
|
||||
r = ret;
|
||||
|
||||
len = BIO_snprintf(buf, sizeof(buf), "BIO[%p]: ", (void *)bio);
|
||||
|
||||
/* Ignore errors and continue printing the other information. */
|
||||
if (len < 0)
|
||||
len = 0;
|
||||
p = buf + len;
|
||||
left = sizeof(buf) - len;
|
||||
|
||||
switch (cmd) {
|
||||
case BIO_CB_FREE:
|
||||
BIO_snprintf(p, left, "Free - %s\n", bio->method->name);
|
||||
break;
|
||||
case BIO_CB_READ:
|
||||
if (bio->method->type & BIO_TYPE_DESCRIPTOR)
|
||||
BIO_snprintf(p, left, "read(%d,%lu) - %s fd=%d\n",
|
||||
bio->num, (unsigned long)argi,
|
||||
bio->method->name, bio->num);
|
||||
else
|
||||
BIO_snprintf(p, left, "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)
|
||||
BIO_snprintf(p, left, "write(%d,%lu) - %s fd=%d\n",
|
||||
bio->num, (unsigned long)argi,
|
||||
bio->method->name, bio->num);
|
||||
else
|
||||
BIO_snprintf(p, left, "write(%d,%lu) - %s\n",
|
||||
bio->num, (unsigned long)argi, bio->method->name);
|
||||
break;
|
||||
case BIO_CB_PUTS:
|
||||
BIO_snprintf(p, left, "puts() - %s\n", bio->method->name);
|
||||
break;
|
||||
case BIO_CB_GETS:
|
||||
BIO_snprintf(p, left, "gets(%lu) - %s\n", (unsigned long)argi,
|
||||
bio->method->name);
|
||||
break;
|
||||
case BIO_CB_CTRL:
|
||||
BIO_snprintf(p, left, "ctrl(%lu) - %s\n", (unsigned long)argi,
|
||||
bio->method->name);
|
||||
break;
|
||||
case BIO_CB_RETURN | BIO_CB_READ:
|
||||
BIO_snprintf(p, left, "read return %ld\n", ret);
|
||||
break;
|
||||
case BIO_CB_RETURN | BIO_CB_WRITE:
|
||||
BIO_snprintf(p, left, "write return %ld\n", ret);
|
||||
break;
|
||||
case BIO_CB_RETURN | BIO_CB_GETS:
|
||||
BIO_snprintf(p, left, "gets return %ld\n", ret);
|
||||
break;
|
||||
case BIO_CB_RETURN | BIO_CB_PUTS:
|
||||
BIO_snprintf(p, left, "puts return %ld\n", ret);
|
||||
break;
|
||||
case BIO_CB_RETURN | BIO_CB_CTRL:
|
||||
BIO_snprintf(p, left, "ctrl return %ld\n", ret);
|
||||
break;
|
||||
default:
|
||||
BIO_snprintf(p, left, "bio callback - unknown type (%d)\n", cmd);
|
||||
break;
|
||||
}
|
||||
|
||||
b = (BIO *)bio->cb_arg;
|
||||
if (b != NULL)
|
||||
BIO_write(b, buf, strlen(buf));
|
||||
#if !defined(OPENSSL_NO_STDIO)
|
||||
else
|
||||
fputs(buf, stderr);
|
||||
#endif
|
||||
return r;
|
||||
}
|
145
trunk/3rdparty/openssl-1.1-fit/crypto/bio/bio_err.c
vendored
Normal file
145
trunk/3rdparty/openssl-1.1-fit/crypto/bio/bio_err.c
vendored
Normal file
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
* Generated by util/mkerr.pl DO NOT EDIT
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/bioerr.h>
|
||||
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
|
||||
static const ERR_STRING_DATA BIO_str_functs[] = {
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_ACPT_STATE, 0), "acpt_state"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_ADDRINFO_WRAP, 0), "addrinfo_wrap"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_ADDR_STRINGS, 0), "addr_strings"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_ACCEPT, 0), "BIO_accept"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_ACCEPT_EX, 0), "BIO_accept_ex"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_ACCEPT_NEW, 0), "BIO_ACCEPT_new"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_ADDR_NEW, 0), "BIO_ADDR_new"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_BIND, 0), "BIO_bind"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_CALLBACK_CTRL, 0), "BIO_callback_ctrl"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_CONNECT, 0), "BIO_connect"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_CONNECT_NEW, 0), "BIO_CONNECT_new"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_CTRL, 0), "BIO_ctrl"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_GETS, 0), "BIO_gets"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_GET_HOST_IP, 0), "BIO_get_host_ip"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_GET_NEW_INDEX, 0), "BIO_get_new_index"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_GET_PORT, 0), "BIO_get_port"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_LISTEN, 0), "BIO_listen"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_LOOKUP, 0), "BIO_lookup"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_LOOKUP_EX, 0), "BIO_lookup_ex"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_MAKE_PAIR, 0), "bio_make_pair"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_METH_NEW, 0), "BIO_meth_new"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_NEW, 0), "BIO_new"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_NEW_DGRAM_SCTP, 0), "BIO_new_dgram_sctp"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_NEW_FILE, 0), "BIO_new_file"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_NEW_MEM_BUF, 0), "BIO_new_mem_buf"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_NREAD, 0), "BIO_nread"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_NREAD0, 0), "BIO_nread0"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_NWRITE, 0), "BIO_nwrite"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_NWRITE0, 0), "BIO_nwrite0"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_PARSE_HOSTSERV, 0), "BIO_parse_hostserv"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_PUTS, 0), "BIO_puts"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_READ, 0), "BIO_read"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_READ_EX, 0), "BIO_read_ex"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_READ_INTERN, 0), "bio_read_intern"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_SOCKET, 0), "BIO_socket"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_SOCKET_NBIO, 0), "BIO_socket_nbio"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_SOCK_INFO, 0), "BIO_sock_info"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_SOCK_INIT, 0), "BIO_sock_init"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_WRITE, 0), "BIO_write"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_WRITE_EX, 0), "BIO_write_ex"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_WRITE_INTERN, 0), "bio_write_intern"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_BUFFER_CTRL, 0), "buffer_ctrl"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_CONN_CTRL, 0), "conn_ctrl"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_CONN_STATE, 0), "conn_state"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_DGRAM_SCTP_NEW, 0), "dgram_sctp_new"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_DGRAM_SCTP_READ, 0), "dgram_sctp_read"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_DGRAM_SCTP_WRITE, 0), "dgram_sctp_write"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_DOAPR_OUTCH, 0), "doapr_outch"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_FILE_CTRL, 0), "file_ctrl"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_FILE_READ, 0), "file_read"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_LINEBUFFER_CTRL, 0), "linebuffer_ctrl"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_LINEBUFFER_NEW, 0), "linebuffer_new"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_MEM_WRITE, 0), "mem_write"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_NBIOF_NEW, 0), "nbiof_new"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_SLG_WRITE, 0), "slg_write"},
|
||||
{ERR_PACK(ERR_LIB_BIO, BIO_F_SSL_NEW, 0), "SSL_new"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
static const ERR_STRING_DATA BIO_str_reasons[] = {
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_ACCEPT_ERROR), "accept error"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_ADDRINFO_ADDR_IS_NOT_AF_INET),
|
||||
"addrinfo addr is not af inet"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_AMBIGUOUS_HOST_OR_SERVICE),
|
||||
"ambiguous host or service"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_BAD_FOPEN_MODE), "bad fopen mode"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_BROKEN_PIPE), "broken pipe"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_CONNECT_ERROR), "connect error"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET),
|
||||
"gethostbyname addr is not af inet"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_GETSOCKNAME_ERROR), "getsockname error"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_GETSOCKNAME_TRUNCATED_ADDRESS),
|
||||
"getsockname truncated address"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_GETTING_SOCKTYPE), "getting socktype"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_INVALID_ARGUMENT), "invalid argument"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_INVALID_SOCKET), "invalid socket"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_IN_USE), "in use"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_LENGTH_TOO_LONG), "length too long"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_LISTEN_V6_ONLY), "listen v6 only"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_LOOKUP_RETURNED_NOTHING),
|
||||
"lookup returned nothing"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_MALFORMED_HOST_OR_SERVICE),
|
||||
"malformed host or service"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_NBIO_CONNECT_ERROR), "nbio connect error"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_NO_ACCEPT_ADDR_OR_SERVICE_SPECIFIED),
|
||||
"no accept addr or service specified"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_NO_HOSTNAME_OR_SERVICE_SPECIFIED),
|
||||
"no hostname or service specified"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_NO_PORT_DEFINED), "no port defined"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_NO_SUCH_FILE), "no such file"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_NULL_PARAMETER), "null parameter"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_UNABLE_TO_BIND_SOCKET),
|
||||
"unable to bind socket"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_UNABLE_TO_CREATE_SOCKET),
|
||||
"unable to create socket"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_UNABLE_TO_KEEPALIVE),
|
||||
"unable to keepalive"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_UNABLE_TO_LISTEN_SOCKET),
|
||||
"unable to listen socket"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_UNABLE_TO_NODELAY), "unable to nodelay"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_UNABLE_TO_REUSEADDR),
|
||||
"unable to reuseaddr"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_UNAVAILABLE_IP_FAMILY),
|
||||
"unavailable ip family"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_UNINITIALIZED), "uninitialized"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_UNKNOWN_INFO_TYPE), "unknown info type"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_UNSUPPORTED_IP_FAMILY),
|
||||
"unsupported ip family"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_UNSUPPORTED_METHOD), "unsupported method"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_UNSUPPORTED_PROTOCOL_FAMILY),
|
||||
"unsupported protocol family"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_WRITE_TO_READ_ONLY_BIO),
|
||||
"write to read only BIO"},
|
||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_WSASTARTUP), "WSAStartup"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
int ERR_load_BIO_strings(void)
|
||||
{
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
if (ERR_func_error_string(BIO_str_functs[0].error) == NULL) {
|
||||
ERR_load_strings_const(BIO_str_functs);
|
||||
ERR_load_strings_const(BIO_str_reasons);
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
190
trunk/3rdparty/openssl-1.1-fit/crypto/bio/bio_lcl.h
vendored
Normal file
190
trunk/3rdparty/openssl-1.1-fit/crypto/bio/bio_lcl.h
vendored
Normal file
|
@ -0,0 +1,190 @@
|
|||
/*
|
||||
* Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include "e_os.h"
|
||||
#include "internal/sockets.h"
|
||||
#include "internal/refcount.h"
|
||||
|
||||
/* BEGIN BIO_ADDRINFO/BIO_ADDR stuff. */
|
||||
|
||||
#ifndef OPENSSL_NO_SOCK
|
||||
/*
|
||||
* Throughout this file and b_addr.c, the existence of the macro
|
||||
* AI_PASSIVE is used to detect the availability of struct addrinfo,
|
||||
* getnameinfo() and getaddrinfo(). If that macro doesn't exist,
|
||||
* we use our own implementation instead.
|
||||
*/
|
||||
|
||||
/*
|
||||
* It's imperative that these macros get defined before openssl/bio.h gets
|
||||
* included. Otherwise, the AI_PASSIVE hack will not work properly.
|
||||
* For clarity, we check for internal/cryptlib.h since it's a common header
|
||||
* that also includes bio.h.
|
||||
*/
|
||||
# ifdef HEADER_CRYPTLIB_H
|
||||
# error internal/cryptlib.h included before bio_lcl.h
|
||||
# endif
|
||||
# ifdef HEADER_BIO_H
|
||||
# error openssl/bio.h included before bio_lcl.h
|
||||
# endif
|
||||
|
||||
/*
|
||||
* Undefine AF_UNIX on systems that define it but don't support it.
|
||||
*/
|
||||
# if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_VMS)
|
||||
# undef AF_UNIX
|
||||
# endif
|
||||
|
||||
# ifdef AI_PASSIVE
|
||||
|
||||
/*
|
||||
* There's a bug in VMS C header file netdb.h, where struct addrinfo
|
||||
* always is the P32 variant, but the functions that handle that structure,
|
||||
* such as getaddrinfo() and freeaddrinfo() adapt to the initial pointer
|
||||
* size. The easiest workaround is to force struct addrinfo to be the
|
||||
* 64-bit variant when compiling in P64 mode.
|
||||
*/
|
||||
# if defined(OPENSSL_SYS_VMS) && __INITIAL_POINTER_SIZE == 64
|
||||
# define addrinfo __addrinfo64
|
||||
# endif
|
||||
|
||||
# define bio_addrinfo_st addrinfo
|
||||
# define bai_family ai_family
|
||||
# define bai_socktype ai_socktype
|
||||
# define bai_protocol ai_protocol
|
||||
# define bai_addrlen ai_addrlen
|
||||
# define bai_addr ai_addr
|
||||
# define bai_next ai_next
|
||||
# else
|
||||
struct bio_addrinfo_st {
|
||||
int bai_family;
|
||||
int bai_socktype;
|
||||
int bai_protocol;
|
||||
size_t bai_addrlen;
|
||||
struct sockaddr *bai_addr;
|
||||
struct bio_addrinfo_st *bai_next;
|
||||
};
|
||||
# endif
|
||||
|
||||
union bio_addr_st {
|
||||
struct sockaddr sa;
|
||||
# ifdef AF_INET6
|
||||
struct sockaddr_in6 s_in6;
|
||||
# endif
|
||||
struct sockaddr_in s_in;
|
||||
# ifdef AF_UNIX
|
||||
struct sockaddr_un s_un;
|
||||
# endif
|
||||
};
|
||||
#endif
|
||||
|
||||
/* END BIO_ADDRINFO/BIO_ADDR stuff. */
|
||||
|
||||
#include "internal/cryptlib.h"
|
||||
#include "internal/bio.h"
|
||||
|
||||
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;
|
||||
|
||||
struct bio_st {
|
||||
const BIO_METHOD *method;
|
||||
/* bio, mode, argp, argi, argl, ret */
|
||||
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 */
|
||||
CRYPTO_REF_COUNT references;
|
||||
uint64_t num_read;
|
||||
uint64_t num_write;
|
||||
CRYPTO_EX_DATA ex_data;
|
||||
CRYPTO_RWLOCK *lock;
|
||||
};
|
||||
|
||||
#ifndef OPENSSL_NO_SOCK
|
||||
# ifdef OPENSSL_SYS_VMS
|
||||
typedef unsigned int socklen_t;
|
||||
# endif
|
||||
|
||||
extern CRYPTO_RWLOCK *bio_lookup_lock;
|
||||
|
||||
int BIO_ADDR_make(BIO_ADDR *ap, const struct sockaddr *sa);
|
||||
const struct sockaddr *BIO_ADDR_sockaddr(const BIO_ADDR *ap);
|
||||
struct sockaddr *BIO_ADDR_sockaddr_noconst(BIO_ADDR *ap);
|
||||
socklen_t BIO_ADDR_sockaddr_size(const BIO_ADDR *ap);
|
||||
socklen_t BIO_ADDRINFO_sockaddr_size(const BIO_ADDRINFO *bai);
|
||||
const struct sockaddr *BIO_ADDRINFO_sockaddr(const BIO_ADDRINFO *bai);
|
||||
#endif
|
||||
|
||||
extern CRYPTO_RWLOCK *bio_type_lock;
|
||||
|
||||
void bio_sock_cleanup_int(void);
|
||||
|
||||
#if BIO_FLAGS_UPLINK==0
|
||||
/* Shortcut UPLINK calls on most platforms... */
|
||||
# define UP_stdin stdin
|
||||
# define UP_stdout stdout
|
||||
# define UP_stderr stderr
|
||||
# define UP_fprintf fprintf
|
||||
# define UP_fgets fgets
|
||||
# define UP_fread fread
|
||||
# define UP_fwrite fwrite
|
||||
# undef UP_fsetmod
|
||||
# define UP_feof feof
|
||||
# define UP_fclose fclose
|
||||
|
||||
# define UP_fopen fopen
|
||||
# define UP_fseek fseek
|
||||
# define UP_ftell ftell
|
||||
# define UP_fflush fflush
|
||||
# define UP_ferror ferror
|
||||
# ifdef _WIN32
|
||||
# define UP_fileno _fileno
|
||||
# define UP_open _open
|
||||
# define UP_read _read
|
||||
# define UP_write _write
|
||||
# define UP_lseek _lseek
|
||||
# define UP_close _close
|
||||
# else
|
||||
# define UP_fileno fileno
|
||||
# define UP_open open
|
||||
# define UP_read read
|
||||
# define UP_write write
|
||||
# define UP_lseek lseek
|
||||
# define UP_close close
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
786
trunk/3rdparty/openssl-1.1-fit/crypto/bio/bio_lib.c
vendored
Normal file
786
trunk/3rdparty/openssl-1.1-fit/crypto/bio/bio_lib.c
vendored
Normal file
|
@ -0,0 +1,786 @@
|
|||
/*
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include "bio_lcl.h"
|
||||
#include "internal/cryptlib.h"
|
||||
|
||||
|
||||
/*
|
||||
* Helper macro for the callback to determine whether an operator expects a
|
||||
* len parameter or not
|
||||
*/
|
||||
#define HAS_LEN_OPER(o) ((o) == BIO_CB_READ || (o) == BIO_CB_WRITE || \
|
||||
(o) == BIO_CB_GETS)
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
||||
/* Strip off any BIO_CB_RETURN flag */
|
||||
bareoper = oper & ~BIO_CB_RETURN;
|
||||
|
||||
/*
|
||||
* We have an old style callback, so we will have to do nasty casts and
|
||||
* check for overflows.
|
||||
*/
|
||||
if (HAS_LEN_OPER(bareoper)) {
|
||||
/* 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;
|
||||
}
|
||||
|
||||
BIO *BIO_new(const BIO_METHOD *method)
|
||||
{
|
||||
BIO *bio = OPENSSL_zalloc(sizeof(*bio));
|
||||
|
||||
if (bio == NULL) {
|
||||
BIOerr(BIO_F_BIO_NEW, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bio->method = method;
|
||||
bio->shutdown = 1;
|
||||
bio->references = 1;
|
||||
|
||||
if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data))
|
||||
goto err;
|
||||
|
||||
bio->lock = CRYPTO_THREAD_lock_new();
|
||||
if (bio->lock == NULL) {
|
||||
BIOerr(BIO_F_BIO_NEW, ERR_R_MALLOC_FAILURE);
|
||||
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (method->create != NULL && !method->create(bio)) {
|
||||
BIOerr(BIO_F_BIO_NEW, ERR_R_INIT_FAIL);
|
||||
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
|
||||
CRYPTO_THREAD_lock_free(bio->lock);
|
||||
goto err;
|
||||
}
|
||||
if (method->create == NULL)
|
||||
bio->init = 1;
|
||||
|
||||
return bio;
|
||||
|
||||
err:
|
||||
OPENSSL_free(bio);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int BIO_free(BIO *a)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (a == NULL)
|
||||
return 0;
|
||||
|
||||
if (CRYPTO_DOWN_REF(&a->references, &ret, a->lock) <= 0)
|
||||
return 0;
|
||||
|
||||
REF_PRINT_COUNT("BIO", a);
|
||||
if (ret > 0)
|
||||
return 1;
|
||||
REF_ASSERT_ISNT(ret < 0);
|
||||
|
||||
if (a->callback != NULL || a->callback_ex != NULL) {
|
||||
ret = (int)bio_call_callback(a, BIO_CB_FREE, NULL, 0, 0, 0L, 1L, NULL);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((a->method != NULL) && (a->method->destroy != NULL))
|
||||
a->method->destroy(a);
|
||||
|
||||
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, a, &a->ex_data);
|
||||
|
||||
CRYPTO_THREAD_lock_free(a->lock);
|
||||
|
||||
OPENSSL_free(a);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void BIO_set_data(BIO *a, void *ptr)
|
||||
{
|
||||
a->ptr = ptr;
|
||||
}
|
||||
|
||||
void *BIO_get_data(BIO *a)
|
||||
{
|
||||
return a->ptr;
|
||||
}
|
||||
|
||||
void BIO_set_init(BIO *a, int init)
|
||||
{
|
||||
a->init = init;
|
||||
}
|
||||
|
||||
int BIO_get_init(BIO *a)
|
||||
{
|
||||
return a->init;
|
||||
}
|
||||
|
||||
void BIO_set_shutdown(BIO *a, int shut)
|
||||
{
|
||||
a->shutdown = shut;
|
||||
}
|
||||
|
||||
int BIO_get_shutdown(BIO *a)
|
||||
{
|
||||
return a->shutdown;
|
||||
}
|
||||
|
||||
void BIO_vfree(BIO *a)
|
||||
{
|
||||
BIO_free(a);
|
||||
}
|
||||
|
||||
int BIO_up_ref(BIO *a)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (CRYPTO_UP_REF(&a->references, &i, a->lock) <= 0)
|
||||
return 0;
|
||||
|
||||
REF_PRINT_COUNT("BIO", a);
|
||||
REF_ASSERT_ISNT(i < 2);
|
||||
return ((i > 1) ? 1 : 0);
|
||||
}
|
||||
|
||||
void BIO_clear_flags(BIO *b, int flags)
|
||||
{
|
||||
b->flags &= ~flags;
|
||||
}
|
||||
|
||||
int BIO_test_flags(const BIO *b, int flags)
|
||||
{
|
||||
return (b->flags & flags);
|
||||
}
|
||||
|
||||
void BIO_set_flags(BIO *b, int flags)
|
||||
{
|
||||
b->flags |= flags;
|
||||
}
|
||||
|
||||
BIO_callback_fn BIO_get_callback(const BIO *b)
|
||||
{
|
||||
return b->callback;
|
||||
}
|
||||
|
||||
void BIO_set_callback(BIO *b, BIO_callback_fn cb)
|
||||
{
|
||||
b->callback = cb;
|
||||
}
|
||||
|
||||
BIO_callback_fn_ex BIO_get_callback_ex(const BIO *b)
|
||||
{
|
||||
return b->callback_ex;
|
||||
}
|
||||
|
||||
void BIO_set_callback_ex(BIO *b, BIO_callback_fn_ex cb)
|
||||
{
|
||||
b->callback_ex = cb;
|
||||
}
|
||||
|
||||
void BIO_set_callback_arg(BIO *b, char *arg)
|
||||
{
|
||||
b->cb_arg = arg;
|
||||
}
|
||||
|
||||
char *BIO_get_callback_arg(const BIO *b)
|
||||
{
|
||||
return b->cb_arg;
|
||||
}
|
||||
|
||||
const char *BIO_method_name(const BIO *b)
|
||||
{
|
||||
return b->method->name;
|
||||
}
|
||||
|
||||
int BIO_method_type(const BIO *b)
|
||||
{
|
||||
return b->method->type;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is essentially the same as BIO_read_ex() except that it allows
|
||||
* 0 or a negative value to indicate failure (retryable or not) in the return.
|
||||
* This is for compatibility with the old style BIO_read(), where existing code
|
||||
* may make assumptions about the return value that it might get.
|
||||
*/
|
||||
static int bio_read_intern(BIO *b, void *data, size_t dlen, size_t *readbytes)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if ((b == NULL) || (b->method == NULL) || (b->method->bread == NULL)) {
|
||||
BIOerr(BIO_F_BIO_READ_INTERN, BIO_R_UNSUPPORTED_METHOD);
|
||||
return -2;
|
||||
}
|
||||
|
||||
if ((b->callback != NULL || b->callback_ex != NULL) &&
|
||||
((ret = (int)bio_call_callback(b, BIO_CB_READ, data, dlen, 0, 0L, 1L,
|
||||
NULL)) <= 0))
|
||||
return ret;
|
||||
|
||||
if (!b->init) {
|
||||
BIOerr(BIO_F_BIO_READ_INTERN, BIO_R_UNINITIALIZED);
|
||||
return -2;
|
||||
}
|
||||
|
||||
ret = b->method->bread(b, data, dlen, readbytes);
|
||||
|
||||
if (ret > 0)
|
||||
b->num_read += (uint64_t)*readbytes;
|
||||
|
||||
if (b->callback != NULL || b->callback_ex != NULL)
|
||||
ret = (int)bio_call_callback(b, BIO_CB_READ | BIO_CB_RETURN, data,
|
||||
dlen, 0, 0L, ret, readbytes);
|
||||
|
||||
/* Shouldn't happen */
|
||||
if (ret > 0 && *readbytes > dlen) {
|
||||
BIOerr(BIO_F_BIO_READ_INTERN, ERR_R_INTERNAL_ERROR);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int BIO_read(BIO *b, void *data, int dlen)
|
||||
{
|
||||
size_t readbytes;
|
||||
int ret;
|
||||
|
||||
if (dlen < 0)
|
||||
return 0;
|
||||
|
||||
ret = bio_read_intern(b, data, (size_t)dlen, &readbytes);
|
||||
|
||||
if (ret > 0) {
|
||||
/* *readbytes should always be <= dlen */
|
||||
ret = (int)readbytes;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int BIO_read_ex(BIO *b, void *data, size_t dlen, size_t *readbytes)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = bio_read_intern(b, data, dlen, readbytes);
|
||||
|
||||
if (ret > 0)
|
||||
ret = 1;
|
||||
else
|
||||
ret = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bio_write_intern(BIO *b, const void *data, size_t dlen,
|
||||
size_t *written)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (b == NULL)
|
||||
return 0;
|
||||
|
||||
if ((b->method == NULL) || (b->method->bwrite == NULL)) {
|
||||
BIOerr(BIO_F_BIO_WRITE_INTERN, BIO_R_UNSUPPORTED_METHOD);
|
||||
return -2;
|
||||
}
|
||||
|
||||
if ((b->callback != NULL || b->callback_ex != NULL) &&
|
||||
((ret = (int)bio_call_callback(b, BIO_CB_WRITE, data, dlen, 0, 0L, 1L,
|
||||
NULL)) <= 0))
|
||||
return ret;
|
||||
|
||||
if (!b->init) {
|
||||
BIOerr(BIO_F_BIO_WRITE_INTERN, BIO_R_UNINITIALIZED);
|
||||
return -2;
|
||||
}
|
||||
|
||||
ret = b->method->bwrite(b, data, dlen, written);
|
||||
|
||||
if (ret > 0)
|
||||
b->num_write += (uint64_t)*written;
|
||||
|
||||
if (b->callback != NULL || b->callback_ex != NULL)
|
||||
ret = (int)bio_call_callback(b, BIO_CB_WRITE | BIO_CB_RETURN, data,
|
||||
dlen, 0, 0L, ret, written);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int BIO_write(BIO *b, const void *data, int dlen)
|
||||
{
|
||||
size_t written;
|
||||
int ret;
|
||||
|
||||
if (dlen < 0)
|
||||
return 0;
|
||||
|
||||
ret = bio_write_intern(b, data, (size_t)dlen, &written);
|
||||
|
||||
if (ret > 0) {
|
||||
/* *written should always be <= dlen */
|
||||
ret = (int)written;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int BIO_write_ex(BIO *b, const void *data, size_t dlen, size_t *written)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = bio_write_intern(b, data, dlen, written);
|
||||
|
||||
if (ret > 0)
|
||||
ret = 1;
|
||||
else
|
||||
ret = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int BIO_puts(BIO *b, const char *buf)
|
||||
{
|
||||
int ret;
|
||||
size_t written = 0;
|
||||
|
||||
if ((b == NULL) || (b->method == NULL) || (b->method->bputs == NULL)) {
|
||||
BIOerr(BIO_F_BIO_PUTS, BIO_R_UNSUPPORTED_METHOD);
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (b->callback != NULL || b->callback_ex != NULL) {
|
||||
ret = (int)bio_call_callback(b, BIO_CB_PUTS, buf, 0, 0, 0L, 1L, NULL);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!b->init) {
|
||||
BIOerr(BIO_F_BIO_PUTS, BIO_R_UNINITIALIZED);
|
||||
return -2;
|
||||
}
|
||||
|
||||
ret = b->method->bputs(b, buf);
|
||||
|
||||
if (ret > 0) {
|
||||
b->num_write += (uint64_t)ret;
|
||||
written = ret;
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
if (b->callback != NULL || b->callback_ex != NULL)
|
||||
ret = (int)bio_call_callback(b, BIO_CB_PUTS | BIO_CB_RETURN, buf, 0, 0,
|
||||
0L, ret, &written);
|
||||
|
||||
if (ret > 0) {
|
||||
if (written > INT_MAX) {
|
||||
BIOerr(BIO_F_BIO_PUTS, BIO_R_LENGTH_TOO_LONG);
|
||||
ret = -1;
|
||||
} else {
|
||||
ret = (int)written;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int BIO_gets(BIO *b, char *buf, int size)
|
||||
{
|
||||
int ret;
|
||||
size_t readbytes = 0;
|
||||
|
||||
if ((b == NULL) || (b->method == NULL) || (b->method->bgets == NULL)) {
|
||||
BIOerr(BIO_F_BIO_GETS, BIO_R_UNSUPPORTED_METHOD);
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (size < 0) {
|
||||
BIOerr(BIO_F_BIO_GETS, BIO_R_INVALID_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (b->callback != NULL || b->callback_ex != NULL) {
|
||||
ret = (int)bio_call_callback(b, BIO_CB_GETS, buf, size, 0, 0L, 1, NULL);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!b->init) {
|
||||
BIOerr(BIO_F_BIO_GETS, BIO_R_UNINITIALIZED);
|
||||
return -2;
|
||||
}
|
||||
|
||||
ret = b->method->bgets(b, buf, size);
|
||||
|
||||
if (ret > 0) {
|
||||
readbytes = ret;
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
if (b->callback != NULL || b->callback_ex != NULL)
|
||||
ret = (int)bio_call_callback(b, BIO_CB_GETS | BIO_CB_RETURN, buf, size,
|
||||
0, 0L, ret, &readbytes);
|
||||
|
||||
if (ret > 0) {
|
||||
/* Shouldn't happen */
|
||||
if (readbytes > (size_t)size)
|
||||
ret = -1;
|
||||
else
|
||||
ret = (int)readbytes;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int BIO_indent(BIO *b, int indent, int max)
|
||||
{
|
||||
if (indent < 0)
|
||||
indent = 0;
|
||||
if (indent > max)
|
||||
indent = max;
|
||||
while (indent--)
|
||||
if (BIO_puts(b, " ") != 1)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
long BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = iarg;
|
||||
return BIO_ctrl(b, cmd, larg, (char *)&i);
|
||||
}
|
||||
|
||||
void *BIO_ptr_ctrl(BIO *b, int cmd, long larg)
|
||||
{
|
||||
void *p = NULL;
|
||||
|
||||
if (BIO_ctrl(b, cmd, larg, (char *)&p) <= 0)
|
||||
return NULL;
|
||||
else
|
||||
return p;
|
||||
}
|
||||
|
||||
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)) {
|
||||
BIOerr(BIO_F_BIO_CTRL, BIO_R_UNSUPPORTED_METHOD);
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (b->callback != NULL || b->callback_ex != NULL) {
|
||||
ret = bio_call_callback(b, BIO_CB_CTRL, parg, 0, cmd, larg, 1L, NULL);
|
||||
if (ret <= 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;
|
||||
}
|
||||
|
||||
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)) {
|
||||
BIOerr(BIO_F_BIO_CALLBACK_CTRL, BIO_R_UNSUPPORTED_METHOD);
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (b->callback != NULL || b->callback_ex != NULL) {
|
||||
ret = bio_call_callback(b, BIO_CB_CTRL, (void *)&fp, 0, cmd, 0, 1L,
|
||||
NULL);
|
||||
if (ret <= 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;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
size_t BIO_ctrl_wpending(BIO *bio)
|
||||
{
|
||||
return BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL);
|
||||
}
|
||||
|
||||
/* put the 'bio' on the end of b's list of operators */
|
||||
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)
|
||||
bio->prev_bio = lb;
|
||||
/* called to do internal processing */
|
||||
BIO_ctrl(b, BIO_CTRL_PUSH, 0, lb);
|
||||
return b;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
int BIO_get_retry_reason(BIO *bio)
|
||||
{
|
||||
return bio->retry_reason;
|
||||
}
|
||||
|
||||
void BIO_set_retry_reason(BIO *bio, int reason)
|
||||
{
|
||||
bio->retry_reason = reason;
|
||||
}
|
||||
|
||||
BIO *BIO_find_type(BIO *bio, int type)
|
||||
{
|
||||
int mt, mask;
|
||||
|
||||
if (bio == NULL)
|
||||
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;
|
||||
}
|
||||
|
||||
BIO *BIO_next(BIO *b)
|
||||
{
|
||||
if (b == NULL)
|
||||
return NULL;
|
||||
return b->next_bio;
|
||||
}
|
||||
|
||||
void BIO_set_next(BIO *b, BIO *next)
|
||||
{
|
||||
b->next_bio = 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;
|
||||
}
|
||||
}
|
||||
|
||||
BIO *BIO_dup_chain(BIO *in)
|
||||
{
|
||||
BIO *ret = NULL, *eoc = NULL, *bio, *new_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;
|
||||
|
||||
/* This will let SSL_s_sock() work with stdin/stdout */
|
||||
new_bio->num = bio->num;
|
||||
|
||||
if (!BIO_dup_state(bio, (char *)new_bio)) {
|
||||
BIO_free(new_bio);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* copy app data */
|
||||
if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_BIO, &new_bio->ex_data,
|
||||
&bio->ex_data)) {
|
||||
BIO_free(new_bio);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (ret == NULL) {
|
||||
eoc = new_bio;
|
||||
ret = eoc;
|
||||
} else {
|
||||
BIO_push(eoc, new_bio);
|
||||
eoc = new_bio;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
err:
|
||||
BIO_free_all(ret);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
int BIO_set_ex_data(BIO *bio, int idx, void *data)
|
||||
{
|
||||
return CRYPTO_set_ex_data(&(bio->ex_data), idx, data);
|
||||
}
|
||||
|
||||
void *BIO_get_ex_data(BIO *bio, int idx)
|
||||
{
|
||||
return CRYPTO_get_ex_data(&(bio->ex_data), idx);
|
||||
}
|
||||
|
||||
uint64_t BIO_number_read(BIO *bio)
|
||||
{
|
||||
if (bio)
|
||||
return bio->num_read;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t BIO_number_written(BIO *bio)
|
||||
{
|
||||
if (bio)
|
||||
return bio->num_write;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bio_free_ex_data(BIO *bio)
|
||||
{
|
||||
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
|
||||
}
|
||||
|
||||
void bio_cleanup(void)
|
||||
{
|
||||
#ifndef OPENSSL_NO_SOCK
|
||||
bio_sock_cleanup_int();
|
||||
CRYPTO_THREAD_lock_free(bio_lookup_lock);
|
||||
bio_lookup_lock = NULL;
|
||||
#endif
|
||||
CRYPTO_THREAD_lock_free(bio_type_lock);
|
||||
bio_type_lock = NULL;
|
||||
}
|
220
trunk/3rdparty/openssl-1.1-fit/crypto/bio/bio_meth.c
vendored
Normal file
220
trunk/3rdparty/openssl-1.1-fit/crypto/bio/bio_meth.c
vendored
Normal file
|
@ -0,0 +1,220 @@
|
|||
/*
|
||||
* Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include "bio_lcl.h"
|
||||
#include "internal/thread_once.h"
|
||||
|
||||
CRYPTO_RWLOCK *bio_type_lock = NULL;
|
||||
static CRYPTO_ONCE bio_type_init = CRYPTO_ONCE_STATIC_INIT;
|
||||
|
||||
DEFINE_RUN_ONCE_STATIC(do_bio_type_init)
|
||||
{
|
||||
bio_type_lock = CRYPTO_THREAD_lock_new();
|
||||
return bio_type_lock != NULL;
|
||||
}
|
||||
|
||||
int BIO_get_new_index(void)
|
||||
{
|
||||
static CRYPTO_REF_COUNT bio_count = BIO_TYPE_START;
|
||||
int newval;
|
||||
|
||||
if (!RUN_ONCE(&bio_type_init, do_bio_type_init)) {
|
||||
BIOerr(BIO_F_BIO_GET_NEW_INDEX, ERR_R_MALLOC_FAILURE);
|
||||
return -1;
|
||||
}
|
||||
if (!CRYPTO_UP_REF(&bio_count, &newval, bio_type_lock))
|
||||
return -1;
|
||||
return newval;
|
||||
}
|
||||
|
||||
BIO_METHOD *BIO_meth_new(int type, const char *name)
|
||||
{
|
||||
BIO_METHOD *biom = OPENSSL_zalloc(sizeof(BIO_METHOD));
|
||||
|
||||
if (biom == NULL
|
||||
|| (biom->name = OPENSSL_strdup(name)) == NULL) {
|
||||
OPENSSL_free(biom);
|
||||
BIOerr(BIO_F_BIO_METH_NEW, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
biom->type = type;
|
||||
return biom;
|
||||
}
|
||||
|
||||
void BIO_meth_free(BIO_METHOD *biom)
|
||||
{
|
||||
if (biom != NULL) {
|
||||
OPENSSL_free(biom->name);
|
||||
OPENSSL_free(biom);
|
||||
}
|
||||
}
|
||||
|
||||
int (*BIO_meth_get_write(const BIO_METHOD *biom)) (BIO *, const char *, int)
|
||||
{
|
||||
return biom->bwrite_old;
|
||||
}
|
||||
|
||||
int (*BIO_meth_get_write_ex(const BIO_METHOD *biom)) (BIO *, const char *, size_t,
|
||||
size_t *)
|
||||
{
|
||||
return biom->bwrite;
|
||||
}
|
||||
|
||||
/* Conversion for old style bwrite to new style */
|
||||
int bwrite_conv(BIO *bio, const char *data, size_t datal, size_t *written)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (datal > INT_MAX)
|
||||
datal = INT_MAX;
|
||||
|
||||
ret = bio->method->bwrite_old(bio, data, (int)datal);
|
||||
|
||||
if (ret <= 0) {
|
||||
*written = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
*written = (size_t)ret;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BIO_meth_set_write(BIO_METHOD *biom,
|
||||
int (*bwrite) (BIO *, const char *, int))
|
||||
{
|
||||
biom->bwrite_old = bwrite;
|
||||
biom->bwrite = bwrite_conv;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BIO_meth_set_write_ex(BIO_METHOD *biom,
|
||||
int (*bwrite) (BIO *, const char *, size_t, size_t *))
|
||||
{
|
||||
biom->bwrite_old = NULL;
|
||||
biom->bwrite = bwrite;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int (*BIO_meth_get_read(const BIO_METHOD *biom)) (BIO *, char *, int)
|
||||
{
|
||||
return biom->bread_old;
|
||||
}
|
||||
|
||||
int (*BIO_meth_get_read_ex(const BIO_METHOD *biom)) (BIO *, char *, size_t, size_t *)
|
||||
{
|
||||
return biom->bread;
|
||||
}
|
||||
|
||||
/* Conversion for old style bread to new style */
|
||||
int bread_conv(BIO *bio, char *data, size_t datal, size_t *readbytes)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (datal > INT_MAX)
|
||||
datal = INT_MAX;
|
||||
|
||||
ret = bio->method->bread_old(bio, data, (int)datal);
|
||||
|
||||
if (ret <= 0) {
|
||||
*readbytes = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
*readbytes = (size_t)ret;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BIO_meth_set_read(BIO_METHOD *biom,
|
||||
int (*bread) (BIO *, char *, int))
|
||||
{
|
||||
biom->bread_old = bread;
|
||||
biom->bread = bread_conv;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BIO_meth_set_read_ex(BIO_METHOD *biom,
|
||||
int (*bread) (BIO *, char *, size_t, size_t *))
|
||||
{
|
||||
biom->bread_old = NULL;
|
||||
biom->bread = bread;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int (*BIO_meth_get_puts(const BIO_METHOD *biom)) (BIO *, const char *)
|
||||
{
|
||||
return biom->bputs;
|
||||
}
|
||||
|
||||
int BIO_meth_set_puts(BIO_METHOD *biom,
|
||||
int (*bputs) (BIO *, const char *))
|
||||
{
|
||||
biom->bputs = bputs;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int (*BIO_meth_get_gets(const BIO_METHOD *biom)) (BIO *, char *, int)
|
||||
{
|
||||
return biom->bgets;
|
||||
}
|
||||
|
||||
int BIO_meth_set_gets(BIO_METHOD *biom,
|
||||
int (*bgets) (BIO *, char *, int))
|
||||
{
|
||||
biom->bgets = bgets;
|
||||
return 1;
|
||||
}
|
||||
|
||||
long (*BIO_meth_get_ctrl(const BIO_METHOD *biom)) (BIO *, int, long, void *)
|
||||
{
|
||||
return biom->ctrl;
|
||||
}
|
||||
|
||||
int BIO_meth_set_ctrl(BIO_METHOD *biom,
|
||||
long (*ctrl) (BIO *, int, long, void *))
|
||||
{
|
||||
biom->ctrl = ctrl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int (*BIO_meth_get_create(const BIO_METHOD *biom)) (BIO *)
|
||||
{
|
||||
return biom->create;
|
||||
}
|
||||
|
||||
int BIO_meth_set_create(BIO_METHOD *biom, int (*create) (BIO *))
|
||||
{
|
||||
biom->create = create;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int (*BIO_meth_get_destroy(const BIO_METHOD *biom)) (BIO *)
|
||||
{
|
||||
return biom->destroy;
|
||||
}
|
||||
|
||||
int BIO_meth_set_destroy(BIO_METHOD *biom, int (*destroy) (BIO *))
|
||||
{
|
||||
biom->destroy = destroy;
|
||||
return 1;
|
||||
}
|
||||
|
||||
long (*BIO_meth_get_callback_ctrl(const BIO_METHOD *biom)) (BIO *, int, BIO_info_cb *)
|
||||
{
|
||||
return biom->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;
|
||||
}
|
560
trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_acpt.c
vendored
Normal file
560
trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_acpt.c
vendored
Normal file
|
@ -0,0 +1,560 @@
|
|||
/*
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include "bio_lcl.h"
|
||||
|
||||
#ifndef OPENSSL_NO_SOCK
|
||||
|
||||
typedef struct bio_accept_st {
|
||||
int state;
|
||||
int accept_family;
|
||||
int bind_mode; /* Socket mode for BIO_listen */
|
||||
int accepted_mode; /* Socket mode for BIO_accept (set on accepted sock) */
|
||||
char *param_addr;
|
||||
char *param_serv;
|
||||
|
||||
int accept_sock;
|
||||
|
||||
BIO_ADDRINFO *addr_first;
|
||||
const BIO_ADDRINFO *addr_iter;
|
||||
BIO_ADDR cache_accepting_addr; /* Useful if we asked for port 0 */
|
||||
char *cache_accepting_name, *cache_accepting_serv;
|
||||
BIO_ADDR cache_peer_addr;
|
||||
char *cache_peer_name, *cache_peer_serv;
|
||||
|
||||
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_ADDR 2
|
||||
# define ACPT_S_CREATE_SOCKET 3
|
||||
# define ACPT_S_LISTEN 4
|
||||
# define ACPT_S_ACCEPT 5
|
||||
# define ACPT_S_OK 6
|
||||
|
||||
static const BIO_METHOD methods_acceptp = {
|
||||
BIO_TYPE_ACCEPT,
|
||||
"socket accept",
|
||||
/* TODO: Convert to new style write function */
|
||||
bwrite_conv,
|
||||
acpt_write,
|
||||
/* TODO: Convert to new style read function */
|
||||
bread_conv,
|
||||
acpt_read,
|
||||
acpt_puts,
|
||||
NULL, /* connect_gets, */
|
||||
acpt_ctrl,
|
||||
acpt_new,
|
||||
acpt_free,
|
||||
NULL, /* connect_callback_ctrl */
|
||||
};
|
||||
|
||||
const BIO_METHOD *BIO_s_accept(void)
|
||||
{
|
||||
return &methods_acceptp;
|
||||
}
|
||||
|
||||
static int acpt_new(BIO *bi)
|
||||
{
|
||||
BIO_ACCEPT *ba;
|
||||
|
||||
bi->init = 0;
|
||||
bi->num = (int)INVALID_SOCKET;
|
||||
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 = OPENSSL_zalloc(sizeof(*ret))) == NULL) {
|
||||
BIOerr(BIO_F_BIO_ACCEPT_NEW, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
ret->accept_family = BIO_FAMILY_IPANY;
|
||||
ret->accept_sock = (int)INVALID_SOCKET;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void BIO_ACCEPT_free(BIO_ACCEPT *a)
|
||||
{
|
||||
if (a == NULL)
|
||||
return;
|
||||
OPENSSL_free(a->param_addr);
|
||||
OPENSSL_free(a->param_serv);
|
||||
BIO_ADDRINFO_free(a->addr_first);
|
||||
OPENSSL_free(a->cache_accepting_name);
|
||||
OPENSSL_free(a->cache_accepting_serv);
|
||||
OPENSSL_free(a->cache_peer_name);
|
||||
OPENSSL_free(a->cache_peer_serv);
|
||||
BIO_free(a->bio_chain);
|
||||
OPENSSL_free(a);
|
||||
}
|
||||
|
||||
static void acpt_close_socket(BIO *bio)
|
||||
{
|
||||
BIO_ACCEPT *c;
|
||||
|
||||
c = (BIO_ACCEPT *)bio->ptr;
|
||||
if (c->accept_sock != (int)INVALID_SOCKET) {
|
||||
shutdown(c->accept_sock, 2);
|
||||
closesocket(c->accept_sock);
|
||||
c->accept_sock = (int)INVALID_SOCKET;
|
||||
bio->num = (int)INVALID_SOCKET;
|
||||
}
|
||||
}
|
||||
|
||||
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, ret = -1;
|
||||
|
||||
for (;;) {
|
||||
switch (c->state) {
|
||||
case ACPT_S_BEFORE:
|
||||
if (c->param_addr == NULL && c->param_serv == NULL) {
|
||||
BIOerr(BIO_F_ACPT_STATE, BIO_R_NO_ACCEPT_ADDR_OR_SERVICE_SPECIFIED);
|
||||
ERR_add_error_data(4,
|
||||
"hostname=", c->param_addr,
|
||||
" service=", c->param_serv);
|
||||
goto exit_loop;
|
||||
}
|
||||
|
||||
/* Because we're starting a new bind, any cached name and serv
|
||||
* are now obsolete and need to be cleaned out.
|
||||
* QUESTION: should this be done in acpt_close_socket() instead?
|
||||
*/
|
||||
OPENSSL_free(c->cache_accepting_name);
|
||||
c->cache_accepting_name = NULL;
|
||||
OPENSSL_free(c->cache_accepting_serv);
|
||||
c->cache_accepting_serv = NULL;
|
||||
OPENSSL_free(c->cache_peer_name);
|
||||
c->cache_peer_name = NULL;
|
||||
OPENSSL_free(c->cache_peer_serv);
|
||||
c->cache_peer_serv = NULL;
|
||||
|
||||
c->state = ACPT_S_GET_ADDR;
|
||||
break;
|
||||
|
||||
case ACPT_S_GET_ADDR:
|
||||
{
|
||||
int family = AF_UNSPEC;
|
||||
switch (c->accept_family) {
|
||||
case BIO_FAMILY_IPV6:
|
||||
if (1) { /* This is a trick we use to avoid bit rot.
|
||||
* at least the "else" part will always be
|
||||
* compiled.
|
||||
*/
|
||||
#ifdef AF_INET6
|
||||
family = AF_INET6;
|
||||
} else {
|
||||
#endif
|
||||
BIOerr(BIO_F_ACPT_STATE, BIO_R_UNAVAILABLE_IP_FAMILY);
|
||||
goto exit_loop;
|
||||
}
|
||||
break;
|
||||
case BIO_FAMILY_IPV4:
|
||||
family = AF_INET;
|
||||
break;
|
||||
case BIO_FAMILY_IPANY:
|
||||
family = AF_UNSPEC;
|
||||
break;
|
||||
default:
|
||||
BIOerr(BIO_F_ACPT_STATE, BIO_R_UNSUPPORTED_IP_FAMILY);
|
||||
goto exit_loop;
|
||||
}
|
||||
if (BIO_lookup(c->param_addr, c->param_serv, BIO_LOOKUP_SERVER,
|
||||
family, SOCK_STREAM, &c->addr_first) == 0)
|
||||
goto exit_loop;
|
||||
}
|
||||
if (c->addr_first == NULL) {
|
||||
BIOerr(BIO_F_ACPT_STATE, BIO_R_LOOKUP_RETURNED_NOTHING);
|
||||
goto exit_loop;
|
||||
}
|
||||
/* We're currently not iterating, but set this as preparation
|
||||
* for possible future development in that regard
|
||||
*/
|
||||
c->addr_iter = c->addr_first;
|
||||
c->state = ACPT_S_CREATE_SOCKET;
|
||||
break;
|
||||
|
||||
case ACPT_S_CREATE_SOCKET:
|
||||
ret = BIO_socket(BIO_ADDRINFO_family(c->addr_iter),
|
||||
BIO_ADDRINFO_socktype(c->addr_iter),
|
||||
BIO_ADDRINFO_protocol(c->addr_iter), 0);
|
||||
if (ret == (int)INVALID_SOCKET) {
|
||||
SYSerr(SYS_F_SOCKET, get_last_socket_error());
|
||||
ERR_add_error_data(4,
|
||||
"hostname=", c->param_addr,
|
||||
" service=", c->param_serv);
|
||||
BIOerr(BIO_F_ACPT_STATE, BIO_R_UNABLE_TO_CREATE_SOCKET);
|
||||
goto exit_loop;
|
||||
}
|
||||
c->accept_sock = ret;
|
||||
b->num = ret;
|
||||
c->state = ACPT_S_LISTEN;
|
||||
break;
|
||||
|
||||
case ACPT_S_LISTEN:
|
||||
{
|
||||
if (!BIO_listen(c->accept_sock,
|
||||
BIO_ADDRINFO_address(c->addr_iter),
|
||||
c->bind_mode)) {
|
||||
BIO_closesocket(c->accept_sock);
|
||||
goto exit_loop;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
union BIO_sock_info_u info;
|
||||
|
||||
info.addr = &c->cache_accepting_addr;
|
||||
if (!BIO_sock_info(c->accept_sock, BIO_SOCK_INFO_ADDRESS,
|
||||
&info)) {
|
||||
BIO_closesocket(c->accept_sock);
|
||||
goto exit_loop;
|
||||
}
|
||||
}
|
||||
|
||||
c->cache_accepting_name =
|
||||
BIO_ADDR_hostname_string(&c->cache_accepting_addr, 1);
|
||||
c->cache_accepting_serv =
|
||||
BIO_ADDR_service_string(&c->cache_accepting_addr, 1);
|
||||
c->state = ACPT_S_ACCEPT;
|
||||
s = -1;
|
||||
ret = 1;
|
||||
goto end;
|
||||
|
||||
case ACPT_S_ACCEPT:
|
||||
if (b->next_bio != NULL) {
|
||||
c->state = ACPT_S_OK;
|
||||
break;
|
||||
}
|
||||
BIO_clear_retry_flags(b);
|
||||
b->retry_reason = 0;
|
||||
|
||||
OPENSSL_free(c->cache_peer_name);
|
||||
c->cache_peer_name = NULL;
|
||||
OPENSSL_free(c->cache_peer_serv);
|
||||
c->cache_peer_serv = NULL;
|
||||
|
||||
s = BIO_accept_ex(c->accept_sock, &c->cache_peer_addr,
|
||||
c->accepted_mode);
|
||||
|
||||
/* If the returned socket is invalid, this might still be
|
||||
* retryable
|
||||
*/
|
||||
if (s < 0) {
|
||||
if (BIO_sock_should_retry(s)) {
|
||||
BIO_set_retry_special(b);
|
||||
b->retry_reason = BIO_RR_ACCEPT;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
/* If it wasn't retryable, we fail */
|
||||
if (s < 0) {
|
||||
ret = s;
|
||||
goto exit_loop;
|
||||
}
|
||||
|
||||
bio = BIO_new_socket(s, BIO_CLOSE);
|
||||
if (bio == NULL)
|
||||
goto exit_loop;
|
||||
|
||||
BIO_set_callback(bio, BIO_get_callback(b));
|
||||
BIO_set_callback_arg(bio, BIO_get_callback_arg(b));
|
||||
|
||||
/*
|
||||
* 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 exit_loop;
|
||||
if (!BIO_push(dbio, bio))
|
||||
goto exit_loop;
|
||||
bio = dbio;
|
||||
}
|
||||
if (BIO_push(b, bio) == NULL)
|
||||
goto exit_loop;
|
||||
|
||||
c->cache_peer_name =
|
||||
BIO_ADDR_hostname_string(&c->cache_peer_addr, 1);
|
||||
c->cache_peer_serv =
|
||||
BIO_ADDR_service_string(&c->cache_peer_addr, 1);
|
||||
c->state = ACPT_S_OK;
|
||||
bio = NULL;
|
||||
ret = 1;
|
||||
goto end;
|
||||
|
||||
case ACPT_S_OK:
|
||||
if (b->next_bio == NULL) {
|
||||
c->state = ACPT_S_ACCEPT;
|
||||
break;
|
||||
}
|
||||
ret = 1;
|
||||
goto end;
|
||||
|
||||
default:
|
||||
ret = 0;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
exit_loop:
|
||||
if (bio != NULL)
|
||||
BIO_free(bio);
|
||||
else if (s >= 0)
|
||||
BIO_closesocket(s);
|
||||
end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
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);
|
||||
BIO_ADDRINFO_free(data->addr_first);
|
||||
data->addr_first = NULL;
|
||||
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) {
|
||||
char *hold_serv = data->param_serv;
|
||||
/* We affect the hostname regardless. However, the input
|
||||
* string might contain a host:service spec, so we must
|
||||
* parse it, which might or might not affect the service
|
||||
*/
|
||||
OPENSSL_free(data->param_addr);
|
||||
data->param_addr = NULL;
|
||||
ret = BIO_parse_hostserv(ptr,
|
||||
&data->param_addr,
|
||||
&data->param_serv,
|
||||
BIO_PARSE_PRIO_SERV);
|
||||
if (hold_serv != data->param_serv)
|
||||
OPENSSL_free(hold_serv);
|
||||
b->init = 1;
|
||||
} else if (num == 1) {
|
||||
OPENSSL_free(data->param_serv);
|
||||
data->param_serv = BUF_strdup(ptr);
|
||||
b->init = 1;
|
||||
} else if (num == 2) {
|
||||
data->bind_mode |= BIO_SOCK_NONBLOCK;
|
||||
} else if (num == 3) {
|
||||
BIO_free(data->bio_chain);
|
||||
data->bio_chain = (BIO *)ptr;
|
||||
} else if (num == 4) {
|
||||
data->accept_family = *(int *)ptr;
|
||||
}
|
||||
} else {
|
||||
if (num == 2) {
|
||||
data->bind_mode &= ~BIO_SOCK_NONBLOCK;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BIO_C_SET_NBIO:
|
||||
if (num != 0)
|
||||
data->accepted_mode |= BIO_SOCK_NONBLOCK;
|
||||
else
|
||||
data->accepted_mode &= ~BIO_SOCK_NONBLOCK;
|
||||
break;
|
||||
case BIO_C_SET_FD:
|
||||
b->num = *((int *)ptr);
|
||||
data->accept_sock = b->num;
|
||||
data->state = ACPT_S_ACCEPT;
|
||||
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 (num == 0 && ptr != NULL) {
|
||||
pp = (char **)ptr;
|
||||
*pp = data->cache_accepting_name;
|
||||
} else if (num == 1 && ptr != NULL) {
|
||||
pp = (char **)ptr;
|
||||
*pp = data->cache_accepting_serv;
|
||||
} else if (num == 2 && ptr != NULL) {
|
||||
pp = (char **)ptr;
|
||||
*pp = data->cache_peer_name;
|
||||
} else if (num == 3 && ptr != NULL) {
|
||||
pp = (char **)ptr;
|
||||
*pp = data->cache_peer_serv;
|
||||
} else if (num == 4) {
|
||||
switch (BIO_ADDRINFO_family(data->addr_iter)) {
|
||||
#ifdef AF_INET6
|
||||
case AF_INET6:
|
||||
ret = BIO_FAMILY_IPV6;
|
||||
break;
|
||||
#endif
|
||||
case AF_INET:
|
||||
ret = BIO_FAMILY_IPV4;
|
||||
break;
|
||||
case 0:
|
||||
ret = data->accept_family;
|
||||
break;
|
||||
default:
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
} 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:
|
||||
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_name(ret, str))
|
||||
return ret;
|
||||
BIO_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
808
trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_bio.c
vendored
Normal file
808
trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_bio.c
vendored
Normal file
|
@ -0,0 +1,808 @@
|
|||
/*
|
||||
* Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "e_os.h"
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bio_lcl.h"
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/crypto.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 = {
|
||||
BIO_TYPE_BIO,
|
||||
"BIO pair",
|
||||
/* TODO: Convert to new style write function */
|
||||
bwrite_conv,
|
||||
bio_write,
|
||||
/* TODO: Convert to new style read function */
|
||||
bread_conv,
|
||||
bio_read,
|
||||
bio_puts,
|
||||
NULL /* no bio_gets */ ,
|
||||
bio_ctrl,
|
||||
bio_new,
|
||||
bio_free,
|
||||
NULL /* no bio_callback_ctrl */
|
||||
};
|
||||
|
||||
const BIO_METHOD *BIO_s_bio(void)
|
||||
{
|
||||
return &methods_biop;
|
||||
}
|
||||
|
||||
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 = OPENSSL_zalloc(sizeof(*b));
|
||||
|
||||
if (b == NULL)
|
||||
return 0;
|
||||
|
||||
/* enough for one TLS record (just a default) */
|
||||
b->size = 17 * 1024;
|
||||
|
||||
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);
|
||||
|
||||
OPENSSL_free(b->buf);
|
||||
OPENSSL_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;
|
||||
}
|
||||
|
||||
/*-
|
||||
* non-copying interface: provide pointer to available data in buffer
|
||||
* bio_nread0: return number of available bytes
|
||||
* bio_nread: also advance index
|
||||
* (example usage: bio_nread0(), read from buffer, bio_nread()
|
||||
* or just bio_nread(), read from buffer)
|
||||
*/
|
||||
/*
|
||||
* WARNING: The non-copying interface is largely untested as of yet and may
|
||||
* contain bugs.
|
||||
*/
|
||||
static ossl_ssize_t bio_nread0(BIO *bio, char **buf)
|
||||
{
|
||||
struct bio_bio_st *b, *peer_b;
|
||||
ossl_ssize_t num;
|
||||
|
||||
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;
|
||||
|
||||
if (peer_b->len == 0) {
|
||||
char dummy;
|
||||
|
||||
/* avoid code duplication -- nothing available for reading */
|
||||
return bio_read(bio, &dummy, 1); /* returns 0 or -1 */
|
||||
}
|
||||
|
||||
num = peer_b->len;
|
||||
if (peer_b->size < peer_b->offset + num)
|
||||
/* no ring buffer wrap-around for non-copying interface */
|
||||
num = peer_b->size - peer_b->offset;
|
||||
assert(num > 0);
|
||||
|
||||
if (buf != NULL)
|
||||
*buf = peer_b->buf + peer_b->offset;
|
||||
return num;
|
||||
}
|
||||
|
||||
static ossl_ssize_t bio_nread(BIO *bio, char **buf, size_t num_)
|
||||
{
|
||||
struct bio_bio_st *b, *peer_b;
|
||||
ossl_ssize_t num, available;
|
||||
|
||||
if (num_ > OSSL_SSIZE_MAX)
|
||||
num = OSSL_SSIZE_MAX;
|
||||
else
|
||||
num = (ossl_ssize_t) num_;
|
||||
|
||||
available = bio_nread0(bio, buf);
|
||||
if (num > available)
|
||||
num = available;
|
||||
if (num <= 0)
|
||||
return num;
|
||||
|
||||
b = bio->ptr;
|
||||
peer_b = b->peer->ptr;
|
||||
|
||||
peer_b->len -= num;
|
||||
if (peer_b->len) {
|
||||
peer_b->offset += num;
|
||||
assert(peer_b->offset <= peer_b->size);
|
||||
if (peer_b->offset == peer_b->size)
|
||||
peer_b->offset = 0;
|
||||
} else
|
||||
peer_b->offset = 0;
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
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 */
|
||||
BIOerr(BIO_F_BIO_WRITE, 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;
|
||||
}
|
||||
|
||||
/*-
|
||||
* non-copying interface: provide pointer to region to write to
|
||||
* bio_nwrite0: check how much space is available
|
||||
* bio_nwrite: also increase length
|
||||
* (example usage: bio_nwrite0(), write to buffer, bio_nwrite()
|
||||
* or just bio_nwrite(), write to buffer)
|
||||
*/
|
||||
static ossl_ssize_t bio_nwrite0(BIO *bio, char **buf)
|
||||
{
|
||||
struct bio_bio_st *b;
|
||||
size_t num;
|
||||
size_t write_offset;
|
||||
|
||||
BIO_clear_retry_flags(bio);
|
||||
|
||||
if (!bio->init)
|
||||
return 0;
|
||||
|
||||
b = bio->ptr;
|
||||
assert(b != NULL);
|
||||
assert(b->peer != NULL);
|
||||
assert(b->buf != NULL);
|
||||
|
||||
b->request = 0;
|
||||
if (b->closed) {
|
||||
BIOerr(BIO_F_BIO_NWRITE0, BIO_R_BROKEN_PIPE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
assert(b->len <= b->size);
|
||||
|
||||
if (b->len == b->size) {
|
||||
BIO_set_retry_write(bio);
|
||||
return -1;
|
||||
}
|
||||
|
||||
num = b->size - b->len;
|
||||
write_offset = b->offset + b->len;
|
||||
if (write_offset >= b->size)
|
||||
write_offset -= b->size;
|
||||
if (write_offset + num > b->size)
|
||||
/*
|
||||
* no ring buffer wrap-around for non-copying interface (to fulfil
|
||||
* the promise by BIO_ctrl_get_write_guarantee, BIO_nwrite may have
|
||||
* to be called twice)
|
||||
*/
|
||||
num = b->size - write_offset;
|
||||
|
||||
if (buf != NULL)
|
||||
*buf = b->buf + write_offset;
|
||||
assert(write_offset + num <= b->size);
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
static ossl_ssize_t bio_nwrite(BIO *bio, char **buf, size_t num_)
|
||||
{
|
||||
struct bio_bio_st *b;
|
||||
ossl_ssize_t num, space;
|
||||
|
||||
if (num_ > OSSL_SSIZE_MAX)
|
||||
num = OSSL_SSIZE_MAX;
|
||||
else
|
||||
num = (ossl_ssize_t) num_;
|
||||
|
||||
space = bio_nwrite0(bio, buf);
|
||||
if (num > space)
|
||||
num = space;
|
||||
if (num <= 0)
|
||||
return num;
|
||||
b = bio->ptr;
|
||||
assert(b != NULL);
|
||||
b->len += num;
|
||||
assert(b->len <= b->size);
|
||||
|
||||
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) {
|
||||
BIOerr(BIO_F_BIO_CTRL, BIO_R_IN_USE);
|
||||
ret = 0;
|
||||
} else if (num == 0) {
|
||||
BIOerr(BIO_F_BIO_CTRL, BIO_R_INVALID_ARGUMENT);
|
||||
ret = 0;
|
||||
} else {
|
||||
size_t new_size = num;
|
||||
|
||||
if (b->size != new_size) {
|
||||
OPENSSL_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;
|
||||
|
||||
case BIO_C_NREAD0:
|
||||
/* prepare for non-copying read */
|
||||
ret = (long)bio_nread0(bio, ptr);
|
||||
break;
|
||||
|
||||
case BIO_C_NREAD:
|
||||
/* non-copying read */
|
||||
ret = (long)bio_nread(bio, ptr, (size_t)num);
|
||||
break;
|
||||
|
||||
case BIO_C_NWRITE0:
|
||||
/* prepare for non-copying write */
|
||||
ret = (long)bio_nwrite0(bio, ptr);
|
||||
break;
|
||||
|
||||
case BIO_C_NWRITE:
|
||||
/* non-copying write */
|
||||
ret = (long)bio_nwrite(bio, ptr, (size_t)num);
|
||||
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:
|
||||
if (b->peer != NULL) {
|
||||
struct bio_bio_st *peer_b = b->peer->ptr;
|
||||
|
||||
if (peer_b->len == 0 && peer_b->closed)
|
||||
ret = 1;
|
||||
else
|
||||
ret = 0;
|
||||
} 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) {
|
||||
BIOerr(BIO_F_BIO_MAKE_PAIR, BIO_R_IN_USE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (b1->buf == NULL) {
|
||||
b1->buf = OPENSSL_malloc(b1->size);
|
||||
if (b1->buf == NULL) {
|
||||
BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
b1->len = 0;
|
||||
b1->offset = 0;
|
||||
}
|
||||
|
||||
if (b2->buf == NULL) {
|
||||
b2->buf = OPENSSL_malloc(b2->size);
|
||||
if (b2->buf == NULL) {
|
||||
BIOerr(BIO_F_BIO_MAKE_PAIR, 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) {
|
||||
BIO_free(bio1);
|
||||
bio1 = NULL;
|
||||
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);
|
||||
}
|
||||
|
||||
size_t BIO_ctrl_get_read_request(BIO *bio)
|
||||
{
|
||||
return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL);
|
||||
}
|
||||
|
||||
int BIO_ctrl_reset_read_request(BIO *bio)
|
||||
{
|
||||
return (BIO_ctrl(bio, BIO_C_RESET_READ_REQUEST, 0, NULL) != 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* BIO_nread0/nread/nwrite0/nwrite are available only for BIO pairs for now
|
||||
* (conceivably some other BIOs could allow non-copying reads and writes
|
||||
* too.)
|
||||
*/
|
||||
int BIO_nread0(BIO *bio, char **buf)
|
||||
{
|
||||
long ret;
|
||||
|
||||
if (!bio->init) {
|
||||
BIOerr(BIO_F_BIO_NREAD0, BIO_R_UNINITIALIZED);
|
||||
return -2;
|
||||
}
|
||||
|
||||
ret = BIO_ctrl(bio, BIO_C_NREAD0, 0, buf);
|
||||
if (ret > INT_MAX)
|
||||
return INT_MAX;
|
||||
else
|
||||
return (int)ret;
|
||||
}
|
||||
|
||||
int BIO_nread(BIO *bio, char **buf, int num)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!bio->init) {
|
||||
BIOerr(BIO_F_BIO_NREAD, BIO_R_UNINITIALIZED);
|
||||
return -2;
|
||||
}
|
||||
|
||||
ret = (int)BIO_ctrl(bio, BIO_C_NREAD, num, buf);
|
||||
if (ret > 0)
|
||||
bio->num_read += ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int BIO_nwrite0(BIO *bio, char **buf)
|
||||
{
|
||||
long ret;
|
||||
|
||||
if (!bio->init) {
|
||||
BIOerr(BIO_F_BIO_NWRITE0, BIO_R_UNINITIALIZED);
|
||||
return -2;
|
||||
}
|
||||
|
||||
ret = BIO_ctrl(bio, BIO_C_NWRITE0, 0, buf);
|
||||
if (ret > INT_MAX)
|
||||
return INT_MAX;
|
||||
else
|
||||
return (int)ret;
|
||||
}
|
||||
|
||||
int BIO_nwrite(BIO *bio, char **buf, int num)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!bio->init) {
|
||||
BIOerr(BIO_F_BIO_NWRITE, BIO_R_UNINITIALIZED);
|
||||
return -2;
|
||||
}
|
||||
|
||||
ret = BIO_ctrl(bio, BIO_C_NWRITE, num, buf);
|
||||
if (ret > 0)
|
||||
bio->num_write += ret;
|
||||
return ret;
|
||||
}
|
540
trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_conn.c
vendored
Normal file
540
trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_conn.c
vendored
Normal file
|
@ -0,0 +1,540 @@
|
|||
/*
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "bio_lcl.h"
|
||||
|
||||
#ifndef OPENSSL_NO_SOCK
|
||||
|
||||
typedef struct bio_connect_st {
|
||||
int state;
|
||||
int connect_family;
|
||||
char *param_hostname;
|
||||
char *param_service;
|
||||
int connect_mode;
|
||||
|
||||
BIO_ADDRINFO *addr_first;
|
||||
const BIO_ADDRINFO *addr_iter;
|
||||
/*
|
||||
* 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);
|
||||
|
||||
#define BIO_CONN_S_BEFORE 1
|
||||
#define BIO_CONN_S_GET_ADDR 2
|
||||
#define BIO_CONN_S_CREATE_SOCKET 3
|
||||
#define BIO_CONN_S_CONNECT 4
|
||||
#define BIO_CONN_S_OK 5
|
||||
#define BIO_CONN_S_BLOCKED_CONNECT 6
|
||||
|
||||
static const BIO_METHOD methods_connectp = {
|
||||
BIO_TYPE_CONNECT,
|
||||
"socket connect",
|
||||
/* TODO: Convert to new style write function */
|
||||
bwrite_conv,
|
||||
conn_write,
|
||||
/* TODO: Convert to new style read function */
|
||||
bread_conv,
|
||||
conn_read,
|
||||
conn_puts,
|
||||
NULL, /* conn_gets, */
|
||||
conn_ctrl,
|
||||
conn_new,
|
||||
conn_free,
|
||||
conn_callback_ctrl,
|
||||
};
|
||||
|
||||
static int conn_state(BIO *b, BIO_CONNECT *c)
|
||||
{
|
||||
int ret = -1, i;
|
||||
BIO_info_cb *cb = NULL;
|
||||
|
||||
if (c->info_callback != NULL)
|
||||
cb = c->info_callback;
|
||||
|
||||
for (;;) {
|
||||
switch (c->state) {
|
||||
case BIO_CONN_S_BEFORE:
|
||||
if (c->param_hostname == NULL && c->param_service == NULL) {
|
||||
BIOerr(BIO_F_CONN_STATE, BIO_R_NO_HOSTNAME_OR_SERVICE_SPECIFIED);
|
||||
ERR_add_error_data(4,
|
||||
"hostname=", c->param_hostname,
|
||||
" service=", c->param_service);
|
||||
goto exit_loop;
|
||||
}
|
||||
c->state = BIO_CONN_S_GET_ADDR;
|
||||
break;
|
||||
|
||||
case BIO_CONN_S_GET_ADDR:
|
||||
{
|
||||
int family = AF_UNSPEC;
|
||||
switch (c->connect_family) {
|
||||
case BIO_FAMILY_IPV6:
|
||||
if (1) { /* This is a trick we use to avoid bit rot.
|
||||
* at least the "else" part will always be
|
||||
* compiled.
|
||||
*/
|
||||
#ifdef AF_INET6
|
||||
family = AF_INET6;
|
||||
} else {
|
||||
#endif
|
||||
BIOerr(BIO_F_CONN_STATE, BIO_R_UNAVAILABLE_IP_FAMILY);
|
||||
goto exit_loop;
|
||||
}
|
||||
break;
|
||||
case BIO_FAMILY_IPV4:
|
||||
family = AF_INET;
|
||||
break;
|
||||
case BIO_FAMILY_IPANY:
|
||||
family = AF_UNSPEC;
|
||||
break;
|
||||
default:
|
||||
BIOerr(BIO_F_CONN_STATE, BIO_R_UNSUPPORTED_IP_FAMILY);
|
||||
goto exit_loop;
|
||||
}
|
||||
if (BIO_lookup(c->param_hostname, c->param_service,
|
||||
BIO_LOOKUP_CLIENT,
|
||||
family, SOCK_STREAM, &c->addr_first) == 0)
|
||||
goto exit_loop;
|
||||
}
|
||||
if (c->addr_first == NULL) {
|
||||
BIOerr(BIO_F_CONN_STATE, BIO_R_LOOKUP_RETURNED_NOTHING);
|
||||
goto exit_loop;
|
||||
}
|
||||
c->addr_iter = c->addr_first;
|
||||
c->state = BIO_CONN_S_CREATE_SOCKET;
|
||||
break;
|
||||
|
||||
case BIO_CONN_S_CREATE_SOCKET:
|
||||
ret = BIO_socket(BIO_ADDRINFO_family(c->addr_iter),
|
||||
BIO_ADDRINFO_socktype(c->addr_iter),
|
||||
BIO_ADDRINFO_protocol(c->addr_iter), 0);
|
||||
if (ret == (int)INVALID_SOCKET) {
|
||||
SYSerr(SYS_F_SOCKET, get_last_socket_error());
|
||||
ERR_add_error_data(4,
|
||||
"hostname=", c->param_hostname,
|
||||
" service=", c->param_service);
|
||||
BIOerr(BIO_F_CONN_STATE, BIO_R_UNABLE_TO_CREATE_SOCKET);
|
||||
goto exit_loop;
|
||||
}
|
||||
b->num = ret;
|
||||
c->state = BIO_CONN_S_CONNECT;
|
||||
break;
|
||||
|
||||
case BIO_CONN_S_CONNECT:
|
||||
BIO_clear_retry_flags(b);
|
||||
ret = BIO_connect(b->num, BIO_ADDRINFO_address(c->addr_iter),
|
||||
BIO_SOCK_KEEPALIVE | c->connect_mode);
|
||||
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;
|
||||
ERR_clear_error();
|
||||
} else if ((c->addr_iter = BIO_ADDRINFO_next(c->addr_iter))
|
||||
!= NULL) {
|
||||
/*
|
||||
* if there are more addresses to try, do that first
|
||||
*/
|
||||
BIO_closesocket(b->num);
|
||||
c->state = BIO_CONN_S_CREATE_SOCKET;
|
||||
ERR_clear_error();
|
||||
break;
|
||||
} else {
|
||||
SYSerr(SYS_F_CONNECT, get_last_socket_error());
|
||||
ERR_add_error_data(4,
|
||||
"hostname=", c->param_hostname,
|
||||
" service=", c->param_service);
|
||||
BIOerr(BIO_F_CONN_STATE, 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);
|
||||
SYSerr(SYS_F_CONNECT, i);
|
||||
ERR_add_error_data(4,
|
||||
"hostname=", c->param_hostname,
|
||||
" service=", c->param_service);
|
||||
BIOerr(BIO_F_CONN_STATE, 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)) == 0)
|
||||
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 = OPENSSL_zalloc(sizeof(*ret))) == NULL) {
|
||||
BIOerr(BIO_F_BIO_CONNECT_NEW, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
ret->state = BIO_CONN_S_BEFORE;
|
||||
ret->connect_family = BIO_FAMILY_IPANY;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void BIO_CONNECT_free(BIO_CONNECT *a)
|
||||
{
|
||||
if (a == NULL)
|
||||
return;
|
||||
OPENSSL_free(a->param_hostname);
|
||||
OPENSSL_free(a->param_service);
|
||||
BIO_ADDRINFO_free(a->addr_first);
|
||||
OPENSSL_free(a);
|
||||
}
|
||||
|
||||
const BIO_METHOD *BIO_s_connect(void)
|
||||
{
|
||||
return &methods_connectp;
|
||||
}
|
||||
|
||||
static int conn_new(BIO *bi)
|
||||
{
|
||||
bi->init = 0;
|
||||
bi->num = (int)INVALID_SOCKET;
|
||||
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 != (int)INVALID_SOCKET) {
|
||||
/* Only do a shutdown if things were established */
|
||||
if (c->state == BIO_CONN_S_OK)
|
||||
shutdown(bio->num, 2);
|
||||
BIO_closesocket(bio->num);
|
||||
bio->num = (int)INVALID_SOCKET;
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
clear_socket_error();
|
||||
ret = readsocket(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;
|
||||
}
|
||||
|
||||
clear_socket_error();
|
||||
ret = writesocket(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 = NULL;
|
||||
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);
|
||||
BIO_ADDRINFO_free(data->addr_first);
|
||||
data->addr_first = NULL;
|
||||
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_service;
|
||||
} else if (num == 2) {
|
||||
*pptr = (const char *)BIO_ADDRINFO_address(data->addr_iter);
|
||||
} else if (num == 3) {
|
||||
switch (BIO_ADDRINFO_family(data->addr_iter)) {
|
||||
# ifdef AF_INET6
|
||||
case AF_INET6:
|
||||
ret = BIO_FAMILY_IPV6;
|
||||
break;
|
||||
# endif
|
||||
case AF_INET:
|
||||
ret = BIO_FAMILY_IPV4;
|
||||
break;
|
||||
case 0:
|
||||
ret = data->connect_family;
|
||||
break;
|
||||
default:
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
break;
|
||||
case BIO_C_SET_CONNECT:
|
||||
if (ptr != NULL) {
|
||||
b->init = 1;
|
||||
if (num == 0) {
|
||||
char *hold_service = data->param_service;
|
||||
/* We affect the hostname regardless. However, the input
|
||||
* string might contain a host:service spec, so we must
|
||||
* parse it, which might or might not affect the service
|
||||
*/
|
||||
OPENSSL_free(data->param_hostname);
|
||||
data->param_hostname = NULL;
|
||||
ret = BIO_parse_hostserv(ptr,
|
||||
&data->param_hostname,
|
||||
&data->param_service,
|
||||
BIO_PARSE_PRIO_HOST);
|
||||
if (hold_service != data->param_service)
|
||||
OPENSSL_free(hold_service);
|
||||
} else if (num == 1) {
|
||||
OPENSSL_free(data->param_service);
|
||||
data->param_service = BUF_strdup(ptr);
|
||||
} else if (num == 2) {
|
||||
const BIO_ADDR *addr = (const BIO_ADDR *)ptr;
|
||||
if (ret) {
|
||||
data->param_hostname = BIO_ADDR_hostname_string(addr, 1);
|
||||
data->param_service = BIO_ADDR_service_string(addr, 1);
|
||||
BIO_ADDRINFO_free(data->addr_first);
|
||||
data->addr_first = NULL;
|
||||
data->addr_iter = NULL;
|
||||
}
|
||||
} else if (num == 3) {
|
||||
data->connect_family = *(int *)ptr;
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BIO_C_SET_NBIO:
|
||||
if (num != 0)
|
||||
data->connect_mode |= BIO_SOCK_NONBLOCK;
|
||||
else
|
||||
data->connect_mode &= ~BIO_SOCK_NONBLOCK;
|
||||
break;
|
||||
case BIO_C_SET_CONNECT_MODE:
|
||||
data->connect_mode = (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_hostname)
|
||||
BIO_set_conn_hostname(dbio, data->param_hostname);
|
||||
if (data->param_service)
|
||||
BIO_set_conn_port(dbio, data->param_service);
|
||||
BIO_set_conn_ip_family(dbio, data->connect_family);
|
||||
BIO_set_conn_mode(dbio, data->connect_mode);
|
||||
/*
|
||||
* FIXME: the cast of the function seems unlikely to be a good
|
||||
* idea
|
||||
*/
|
||||
(void)BIO_set_info_callback(dbio, data->info_callback);
|
||||
}
|
||||
break;
|
||||
case BIO_CTRL_SET_CALLBACK:
|
||||
ret = 0; /* use callback ctrl */
|
||||
break;
|
||||
case BIO_CTRL_GET_CALLBACK:
|
||||
{
|
||||
BIO_info_cb **fptr;
|
||||
|
||||
fptr = (BIO_info_cb **)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 = 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;
|
||||
BIO_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
1925
trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_dgram.c
vendored
Normal file
1925
trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_dgram.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
280
trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_fd.c
vendored
Normal file
280
trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_fd.c
vendored
Normal file
|
@ -0,0 +1,280 @@
|
|||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "bio_lcl.h"
|
||||
|
||||
#if defined(OPENSSL_NO_POSIX_IO)
|
||||
/*
|
||||
* Dummy placeholder for BIO_s_fd...
|
||||
*/
|
||||
BIO *BIO_new_fd(int fd, int close_flag)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int BIO_fd_non_fatal_error(int err)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int BIO_fd_should_retry(int i)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const BIO_METHOD *BIO_s_fd(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
/*
|
||||
* As for unconditional usage of "UPLINK" interface in this module.
|
||||
* Trouble is that unlike Unix file descriptors [which are indexes
|
||||
* in kernel-side per-process table], corresponding descriptors on
|
||||
* platforms which require "UPLINK" interface seem to be indexes
|
||||
* in a user-land, non-global table. Well, in fact they are indexes
|
||||
* in stdio _iob[], and recall that _iob[] was the very reason why
|
||||
* "UPLINK" interface was introduced in first place. But one way on
|
||||
* another. Neither libcrypto or libssl use this BIO meaning that
|
||||
* file descriptors can only be provided by application. Therefore
|
||||
* "UPLINK" calls are due...
|
||||
*/
|
||||
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 = {
|
||||
BIO_TYPE_FD,
|
||||
"file descriptor",
|
||||
/* TODO: Convert to new style write function */
|
||||
bwrite_conv,
|
||||
fd_write,
|
||||
/* TODO: Convert to new style read function */
|
||||
bread_conv,
|
||||
fd_read,
|
||||
fd_puts,
|
||||
fd_gets,
|
||||
fd_ctrl,
|
||||
fd_new,
|
||||
fd_free,
|
||||
NULL, /* fd_callback_ctrl */
|
||||
};
|
||||
|
||||
const BIO_METHOD *BIO_s_fd(void)
|
||||
{
|
||||
return &methods_fdp;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static int fd_new(BIO *bi)
|
||||
{
|
||||
bi->init = 0;
|
||||
bi->num = -1;
|
||||
bi->ptr = NULL;
|
||||
bi->flags = BIO_FLAGS_UPLINK; /* essentially redundant */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int fd_free(BIO *a)
|
||||
{
|
||||
if (a == NULL)
|
||||
return 0;
|
||||
if (a->shutdown) {
|
||||
if (a->init) {
|
||||
UP_close(a->num);
|
||||
}
|
||||
a->init = 0;
|
||||
a->flags = BIO_FLAGS_UPLINK;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int fd_read(BIO *b, char *out, int outl)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (out != NULL) {
|
||||
clear_sys_error();
|
||||
ret = UP_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;
|
||||
clear_sys_error();
|
||||
ret = UP_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;
|
||||
/* fall thru */
|
||||
case BIO_C_FILE_SEEK:
|
||||
ret = (long)UP_lseek(b->num, num, 0);
|
||||
break;
|
||||
case BIO_C_FILE_TELL:
|
||||
case BIO_CTRL_INFO:
|
||||
ret = (long)UP_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) {
|
||||
if (*ptr++ == '\n')
|
||||
break;
|
||||
}
|
||||
|
||||
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 = get_last_sys_error();
|
||||
|
||||
return BIO_fd_non_fatal_error(err);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int BIO_fd_non_fatal_error(int err)
|
||||
{
|
||||
switch (err) {
|
||||
|
||||
# ifdef EWOULDBLOCK
|
||||
# ifdef WSAEWOULDBLOCK
|
||||
# if WSAEWOULDBLOCK != EWOULDBLOCK
|
||||
case EWOULDBLOCK:
|
||||
# endif
|
||||
# else
|
||||
case EWOULDBLOCK:
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# if defined(ENOTCONN)
|
||||
case ENOTCONN:
|
||||
# endif
|
||||
|
||||
# ifdef EINTR
|
||||
case EINTR:
|
||||
# endif
|
||||
|
||||
# ifdef EAGAIN
|
||||
# if EWOULDBLOCK != EAGAIN
|
||||
case EAGAIN:
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifdef EPROTO
|
||||
case EPROTO:
|
||||
# endif
|
||||
|
||||
# ifdef EINPROGRESS
|
||||
case EINPROGRESS:
|
||||
# endif
|
||||
|
||||
# ifdef EALREADY
|
||||
case EALREADY:
|
||||
# endif
|
||||
return 1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
427
trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_file.c
vendored
Normal file
427
trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_file.c
vendored
Normal file
|
@ -0,0 +1,427 @@
|
|||
/*
|
||||
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#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 <stdio.h>
|
||||
# include <errno.h>
|
||||
# include "bio_lcl.h"
|
||||
# include <openssl/err.h>
|
||||
|
||||
# if !defined(OPENSSL_NO_STDIO)
|
||||
|
||||
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 = {
|
||||
BIO_TYPE_FILE,
|
||||
"FILE pointer",
|
||||
/* TODO: Convert to new style write function */
|
||||
bwrite_conv,
|
||||
file_write,
|
||||
/* TODO: Convert to new style read function */
|
||||
bread_conv,
|
||||
file_read,
|
||||
file_puts,
|
||||
file_gets,
|
||||
file_ctrl,
|
||||
file_new,
|
||||
file_free,
|
||||
NULL, /* file_callback_ctrl */
|
||||
};
|
||||
|
||||
BIO *BIO_new_file(const char *filename, const char *mode)
|
||||
{
|
||||
BIO *ret;
|
||||
FILE *file = openssl_fopen(filename, mode);
|
||||
int fp_flags = BIO_CLOSE;
|
||||
|
||||
if (strchr(mode, 'b') == NULL)
|
||||
fp_flags |= BIO_FP_TEXT;
|
||||
|
||||
if (file == NULL) {
|
||||
SYSerr(SYS_F_FOPEN, get_last_sys_error());
|
||||
ERR_add_error_data(5, "fopen('", filename, "','", mode, "')");
|
||||
if (errno == ENOENT
|
||||
# ifdef ENXIO
|
||||
|| errno == ENXIO
|
||||
# endif
|
||||
)
|
||||
BIOerr(BIO_F_BIO_NEW_FILE, BIO_R_NO_SUCH_FILE);
|
||||
else
|
||||
BIOerr(BIO_F_BIO_NEW_FILE, ERR_R_SYS_LIB);
|
||||
return NULL;
|
||||
}
|
||||
if ((ret = BIO_new(BIO_s_file())) == NULL) {
|
||||
fclose(file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BIO_clear_flags(ret, BIO_FLAGS_UPLINK); /* we did fopen -> we disengage
|
||||
* UPLINK */
|
||||
BIO_set_fp(ret, file, fp_flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
BIO *BIO_new_fp(FILE *stream, int close_flag)
|
||||
{
|
||||
BIO *ret;
|
||||
|
||||
if ((ret = BIO_new(BIO_s_file())) == NULL)
|
||||
return NULL;
|
||||
|
||||
/* redundant flag, left for documentation purposes */
|
||||
BIO_set_flags(ret, BIO_FLAGS_UPLINK);
|
||||
BIO_set_fp(ret, stream, close_flag);
|
||||
return ret;
|
||||
}
|
||||
|
||||
const BIO_METHOD *BIO_s_file(void)
|
||||
{
|
||||
return &methods_filep;
|
||||
}
|
||||
|
||||
static int file_new(BIO *bi)
|
||||
{
|
||||
bi->init = 0;
|
||||
bi->num = 0;
|
||||
bi->ptr = NULL;
|
||||
bi->flags = BIO_FLAGS_UPLINK; /* default to UPLINK */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int file_free(BIO *a)
|
||||
{
|
||||
if (a == NULL)
|
||||
return 0;
|
||||
if (a->shutdown) {
|
||||
if ((a->init) && (a->ptr != NULL)) {
|
||||
if (a->flags & BIO_FLAGS_UPLINK)
|
||||
UP_fclose(a->ptr);
|
||||
else
|
||||
fclose(a->ptr);
|
||||
a->ptr = NULL;
|
||||
a->flags = BIO_FLAGS_UPLINK;
|
||||
}
|
||||
a->init = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int file_read(BIO *b, char *out, int outl)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (b->init && (out != NULL)) {
|
||||
if (b->flags & BIO_FLAGS_UPLINK)
|
||||
ret = UP_fread(out, 1, (int)outl, b->ptr);
|
||||
else
|
||||
ret = fread(out, 1, (int)outl, (FILE *)b->ptr);
|
||||
if (ret == 0
|
||||
&& (b->flags & BIO_FLAGS_UPLINK) ? UP_ferror((FILE *)b->ptr) :
|
||||
ferror((FILE *)b->ptr)) {
|
||||
SYSerr(SYS_F_FREAD, get_last_sys_error());
|
||||
BIOerr(BIO_F_FILE_READ, 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)) {
|
||||
if (b->flags & BIO_FLAGS_UPLINK)
|
||||
ret = UP_fwrite(in, (int)inl, 1, b->ptr);
|
||||
else
|
||||
ret = fwrite(in, (int)inl, 1, (FILE *)b->ptr);
|
||||
if (ret)
|
||||
ret = inl;
|
||||
/* ret=fwrite(in,1,(int)inl,(FILE *)b->ptr); */
|
||||
/*
|
||||
* according to Tim Hudson <tjh@openssl.org>, the commented out
|
||||
* version above can cause 'inl' write calls under some stupid stdio
|
||||
* implementations (VMS)
|
||||
*/
|
||||
}
|
||||
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];
|
||||
int st;
|
||||
|
||||
switch (cmd) {
|
||||
case BIO_C_FILE_SEEK:
|
||||
case BIO_CTRL_RESET:
|
||||
if (b->flags & BIO_FLAGS_UPLINK)
|
||||
ret = (long)UP_fseek(b->ptr, num, 0);
|
||||
else
|
||||
ret = (long)fseek(fp, num, 0);
|
||||
break;
|
||||
case BIO_CTRL_EOF:
|
||||
if (b->flags & BIO_FLAGS_UPLINK)
|
||||
ret = (long)UP_feof(fp);
|
||||
else
|
||||
ret = (long)feof(fp);
|
||||
break;
|
||||
case BIO_C_FILE_TELL:
|
||||
case BIO_CTRL_INFO:
|
||||
if (b->flags & BIO_FLAGS_UPLINK)
|
||||
ret = UP_ftell(b->ptr);
|
||||
else
|
||||
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;
|
||||
# if BIO_FLAGS_UPLINK!=0
|
||||
# if defined(__MINGW32__) && defined(__MSVCRT__) && !defined(_IOB_ENTRIES)
|
||||
# define _IOB_ENTRIES 20
|
||||
# endif
|
||||
/* Safety net to catch purely internal BIO_set_fp calls */
|
||||
# if defined(_MSC_VER) && _MSC_VER>=1900
|
||||
if (ptr == stdin || ptr == stdout || ptr == stderr)
|
||||
BIO_clear_flags(b, BIO_FLAGS_UPLINK);
|
||||
# elif defined(_IOB_ENTRIES)
|
||||
if ((size_t)ptr >= (size_t)stdin &&
|
||||
(size_t)ptr < (size_t)(stdin + _IOB_ENTRIES))
|
||||
BIO_clear_flags(b, BIO_FLAGS_UPLINK);
|
||||
# endif
|
||||
# endif
|
||||
# ifdef UP_fsetmod
|
||||
if (b->flags & BIO_FLAGS_UPLINK)
|
||||
UP_fsetmod(b->ptr, (char)((num & BIO_FP_TEXT) ? 't' : 'b'));
|
||||
else
|
||||
# endif
|
||||
{
|
||||
# if defined(OPENSSL_SYS_WINDOWS)
|
||||
int fd = _fileno((FILE *)ptr);
|
||||
if (num & BIO_FP_TEXT)
|
||||
_setmode(fd, _O_TEXT);
|
||||
else
|
||||
_setmode(fd, _O_BINARY);
|
||||
# elif defined(OPENSSL_SYS_MSDOS)
|
||||
int fd = fileno((FILE *)ptr);
|
||||
/* Set correct text/binary mode */
|
||||
if (num & BIO_FP_TEXT)
|
||||
_setmode(fd, _O_TEXT);
|
||||
/* Dangerous to set stdin/stdout to raw (unless redirected) */
|
||||
else {
|
||||
if (fd == STDIN_FILENO || fd == STDOUT_FILENO) {
|
||||
if (isatty(fd) <= 0)
|
||||
_setmode(fd, _O_BINARY);
|
||||
} else
|
||||
_setmode(fd, _O_BINARY);
|
||||
}
|
||||
# elif defined(OPENSSL_SYS_WIN32_CYGWIN)
|
||||
int fd = fileno((FILE *)ptr);
|
||||
if (!(num & BIO_FP_TEXT))
|
||||
setmode(fd, O_BINARY);
|
||||
# endif
|
||||
}
|
||||
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)
|
||||
OPENSSL_strlcpy(p, "a+", sizeof(p));
|
||||
else
|
||||
OPENSSL_strlcpy(p, "a", sizeof(p));
|
||||
} else if ((num & BIO_FP_READ) && (num & BIO_FP_WRITE))
|
||||
OPENSSL_strlcpy(p, "r+", sizeof(p));
|
||||
else if (num & BIO_FP_WRITE)
|
||||
OPENSSL_strlcpy(p, "w", sizeof(p));
|
||||
else if (num & BIO_FP_READ)
|
||||
OPENSSL_strlcpy(p, "r", sizeof(p));
|
||||
else {
|
||||
BIOerr(BIO_F_FILE_CTRL, BIO_R_BAD_FOPEN_MODE);
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
# if defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_WINDOWS)
|
||||
if (!(num & BIO_FP_TEXT))
|
||||
OPENSSL_strlcat(p, "b", sizeof(p));
|
||||
else
|
||||
OPENSSL_strlcat(p, "t", sizeof(p));
|
||||
# elif defined(OPENSSL_SYS_WIN32_CYGWIN)
|
||||
if (!(num & BIO_FP_TEXT))
|
||||
OPENSSL_strlcat(p, "b", sizeof(p));
|
||||
# endif
|
||||
fp = openssl_fopen(ptr, p);
|
||||
if (fp == NULL) {
|
||||
SYSerr(SYS_F_FOPEN, get_last_sys_error());
|
||||
ERR_add_error_data(5, "fopen('", ptr, "','", p, "')");
|
||||
BIOerr(BIO_F_FILE_CTRL, ERR_R_SYS_LIB);
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
b->ptr = fp;
|
||||
b->init = 1;
|
||||
BIO_clear_flags(b, BIO_FLAGS_UPLINK); /* we did fopen -> we disengage
|
||||
* UPLINK */
|
||||
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:
|
||||
st = b->flags & BIO_FLAGS_UPLINK
|
||||
? UP_fflush(b->ptr) : fflush((FILE *)b->ptr);
|
||||
if (st == EOF) {
|
||||
SYSerr(SYS_F_FFLUSH, get_last_sys_error());
|
||||
ERR_add_error_data(1, "fflush()");
|
||||
BIOerr(BIO_F_FILE_CTRL, ERR_R_SYS_LIB);
|
||||
ret = 0;
|
||||
}
|
||||
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 (bp->flags & BIO_FLAGS_UPLINK) {
|
||||
if (!UP_fgets(buf, size, bp->ptr))
|
||||
goto err;
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static int file_write(BIO *b, const char *in, int inl)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
static int file_read(BIO *b, char *out, int outl)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
static int file_puts(BIO *bp, const char *str)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
static int file_gets(BIO *bp, char *buf, int size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static long file_ctrl(BIO *b, int cmd, long num, void *ptr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static int file_new(BIO *bi)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static int file_free(BIO *a)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const BIO_METHOD methods_filep = {
|
||||
BIO_TYPE_FILE,
|
||||
"FILE pointer",
|
||||
/* TODO: Convert to new style write function */
|
||||
bwrite_conv,
|
||||
file_write,
|
||||
/* TODO: Convert to new style read function */
|
||||
bread_conv,
|
||||
file_read,
|
||||
file_puts,
|
||||
file_gets,
|
||||
file_ctrl,
|
||||
file_new,
|
||||
file_free,
|
||||
NULL, /* file_callback_ctrl */
|
||||
};
|
||||
|
||||
const BIO_METHOD *BIO_s_file(void)
|
||||
{
|
||||
return &methods_filep;
|
||||
}
|
||||
|
||||
BIO *BIO_new_file(const char *filename, const char *mode)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
# endif /* OPENSSL_NO_STDIO */
|
||||
|
||||
#endif /* HEADER_BSS_FILE_C */
|
416
trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_log.c
vendored
Normal file
416
trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_log.c
vendored
Normal file
|
@ -0,0 +1,416 @@
|
|||
/*
|
||||
* Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "bio_lcl.h"
|
||||
#include "internal/cryptlib.h"
|
||||
|
||||
#if defined(OPENSSL_SYS_WINCE)
|
||||
#elif defined(OPENSSL_SYS_WIN32)
|
||||
#elif defined(OPENSSL_SYS_VMS)
|
||||
# include <opcdef.h>
|
||||
# include <descrip.h>
|
||||
# include <lib$routines.h>
|
||||
# include <starlet.h>
|
||||
/* Some compiler options may mask the declaration of "_malloc32". */
|
||||
# if __INITIAL_POINTER_SIZE && defined _ANSI_C_SOURCE
|
||||
# if __INITIAL_POINTER_SIZE == 64
|
||||
# pragma pointer_size save
|
||||
# pragma pointer_size 32
|
||||
void *_malloc32(__size_t);
|
||||
# pragma pointer_size restore
|
||||
# endif /* __INITIAL_POINTER_SIZE == 64 */
|
||||
# endif /* __INITIAL_POINTER_SIZE && defined
|
||||
* _ANSI_C_SOURCE */
|
||||
#elif defined(__DJGPP__) && defined(OPENSSL_NO_SOCK)
|
||||
# define NO_SYSLOG
|
||||
#elif (!defined(MSDOS) || defined(WATT32)) && !defined(OPENSSL_SYS_VXWORKS) && !defined(NO_SYSLOG)
|
||||
# include <syslog.h>
|
||||
#endif
|
||||
|
||||
#include <openssl/buffer.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#ifndef NO_SYSLOG
|
||||
|
||||
# if defined(OPENSSL_SYS_WIN32)
|
||||
# define LOG_EMERG 0
|
||||
# define LOG_ALERT 1
|
||||
# define LOG_CRIT 2
|
||||
# define LOG_ERR 3
|
||||
# define LOG_WARNING 4
|
||||
# define LOG_NOTICE 5
|
||||
# define LOG_INFO 6
|
||||
# define LOG_DEBUG 7
|
||||
|
||||
# define LOG_DAEMON (3<<3)
|
||||
# elif defined(OPENSSL_SYS_VMS)
|
||||
/* On VMS, we don't really care about these, but we need them to compile */
|
||||
# define LOG_EMERG 0
|
||||
# define LOG_ALERT 1
|
||||
# define LOG_CRIT 2
|
||||
# define LOG_ERR 3
|
||||
# define LOG_WARNING 4
|
||||
# define LOG_NOTICE 5
|
||||
# define LOG_INFO 6
|
||||
# define LOG_DEBUG 7
|
||||
|
||||
# define LOG_DAEMON OPC$M_NM_NTWORK
|
||||
# endif
|
||||
|
||||
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 = {
|
||||
BIO_TYPE_MEM,
|
||||
"syslog",
|
||||
/* TODO: Convert to new style write function */
|
||||
bwrite_conv,
|
||||
slg_write,
|
||||
NULL, /* slg_write_old, */
|
||||
NULL, /* slg_read, */
|
||||
slg_puts,
|
||||
NULL,
|
||||
slg_ctrl,
|
||||
slg_new,
|
||||
slg_free,
|
||||
NULL, /* slg_callback_ctrl */
|
||||
};
|
||||
|
||||
const BIO_METHOD *BIO_s_log(void)
|
||||
{
|
||||
return &methods_slg;
|
||||
}
|
||||
|
||||
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 = OPENSSL_malloc(inl + 1)) == NULL) {
|
||||
BIOerr(BIO_F_SLG_WRITE, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
memcpy(buf, in, inl);
|
||||
buf[inl] = '\0';
|
||||
|
||||
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);
|
||||
|
||||
OPENSSL_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;
|
||||
}
|
||||
|
||||
# if defined(OPENSSL_SYS_WIN32)
|
||||
|
||||
static void xopenlog(BIO *bp, char *name, int level)
|
||||
{
|
||||
if (check_winnt())
|
||||
bp->ptr = RegisterEventSourceA(NULL, name);
|
||||
else
|
||||
bp->ptr = NULL;
|
||||
}
|
||||
|
||||
static void xsyslog(BIO *bp, int priority, const char *string)
|
||||
{
|
||||
LPCSTR lpszStrings[2];
|
||||
WORD evtype = EVENTLOG_ERROR_TYPE;
|
||||
char pidbuf[DECIMAL_SIZE(DWORD) + 4];
|
||||
|
||||
if (bp->ptr == NULL)
|
||||
return;
|
||||
|
||||
switch (priority) {
|
||||
case LOG_EMERG:
|
||||
case LOG_ALERT:
|
||||
case LOG_CRIT:
|
||||
case LOG_ERR:
|
||||
evtype = EVENTLOG_ERROR_TYPE;
|
||||
break;
|
||||
case LOG_WARNING:
|
||||
evtype = EVENTLOG_WARNING_TYPE;
|
||||
break;
|
||||
case LOG_NOTICE:
|
||||
case LOG_INFO:
|
||||
case LOG_DEBUG:
|
||||
evtype = EVENTLOG_INFORMATION_TYPE;
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
* Should never happen, but set it
|
||||
* as error anyway.
|
||||
*/
|
||||
evtype = EVENTLOG_ERROR_TYPE;
|
||||
break;
|
||||
}
|
||||
|
||||
sprintf(pidbuf, "[%lu] ", GetCurrentProcessId());
|
||||
lpszStrings[0] = pidbuf;
|
||||
lpszStrings[1] = string;
|
||||
|
||||
ReportEventA(bp->ptr, evtype, 0, 1024, NULL, 2, 0, lpszStrings, NULL);
|
||||
}
|
||||
|
||||
static void xcloselog(BIO *bp)
|
||||
{
|
||||
if (bp->ptr)
|
||||
DeregisterEventSource((HANDLE) (bp->ptr));
|
||||
bp->ptr = NULL;
|
||||
}
|
||||
|
||||
# elif defined(OPENSSL_SYS_VMS)
|
||||
|
||||
static int VMS_OPC_target = LOG_DAEMON;
|
||||
|
||||
static void xopenlog(BIO *bp, char *name, int level)
|
||||
{
|
||||
VMS_OPC_target = level;
|
||||
}
|
||||
|
||||
static void xsyslog(BIO *bp, int priority, const char *string)
|
||||
{
|
||||
struct dsc$descriptor_s opc_dsc;
|
||||
|
||||
/* Arrange 32-bit pointer to opcdef buffer and malloc(), if needed. */
|
||||
# if __INITIAL_POINTER_SIZE == 64
|
||||
# pragma pointer_size save
|
||||
# pragma pointer_size 32
|
||||
# define OPCDEF_TYPE __char_ptr32
|
||||
# define OPCDEF_MALLOC _malloc32
|
||||
# else /* __INITIAL_POINTER_SIZE == 64 */
|
||||
# define OPCDEF_TYPE char *
|
||||
# define OPCDEF_MALLOC OPENSSL_malloc
|
||||
# endif /* __INITIAL_POINTER_SIZE == 64 [else] */
|
||||
|
||||
struct opcdef *opcdef_p;
|
||||
|
||||
# if __INITIAL_POINTER_SIZE == 64
|
||||
# pragma pointer_size restore
|
||||
# endif /* __INITIAL_POINTER_SIZE == 64 */
|
||||
|
||||
char buf[10240];
|
||||
unsigned int len;
|
||||
struct dsc$descriptor_s buf_dsc;
|
||||
$DESCRIPTOR(fao_cmd, "!AZ: !AZ");
|
||||
char *priority_tag;
|
||||
|
||||
switch (priority) {
|
||||
case LOG_EMERG:
|
||||
priority_tag = "Emergency";
|
||||
break;
|
||||
case LOG_ALERT:
|
||||
priority_tag = "Alert";
|
||||
break;
|
||||
case LOG_CRIT:
|
||||
priority_tag = "Critical";
|
||||
break;
|
||||
case LOG_ERR:
|
||||
priority_tag = "Error";
|
||||
break;
|
||||
case LOG_WARNING:
|
||||
priority_tag = "Warning";
|
||||
break;
|
||||
case LOG_NOTICE:
|
||||
priority_tag = "Notice";
|
||||
break;
|
||||
case LOG_INFO:
|
||||
priority_tag = "Info";
|
||||
break;
|
||||
case LOG_DEBUG:
|
||||
priority_tag = "DEBUG";
|
||||
break;
|
||||
}
|
||||
|
||||
buf_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
|
||||
buf_dsc.dsc$b_class = DSC$K_CLASS_S;
|
||||
buf_dsc.dsc$a_pointer = buf;
|
||||
buf_dsc.dsc$w_length = sizeof(buf) - 1;
|
||||
|
||||
lib$sys_fao(&fao_cmd, &len, &buf_dsc, priority_tag, string);
|
||||
|
||||
/* We know there's an 8-byte header. That's documented. */
|
||||
opcdef_p = OPCDEF_MALLOC(8 + len);
|
||||
opcdef_p->opc$b_ms_type = OPC$_RQ_RQST;
|
||||
memcpy(opcdef_p->opc$z_ms_target_classes, &VMS_OPC_target, 3);
|
||||
opcdef_p->opc$l_ms_rqstid = 0;
|
||||
memcpy(&opcdef_p->opc$l_ms_text, buf, len);
|
||||
|
||||
opc_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
|
||||
opc_dsc.dsc$b_class = DSC$K_CLASS_S;
|
||||
opc_dsc.dsc$a_pointer = (OPCDEF_TYPE) opcdef_p;
|
||||
opc_dsc.dsc$w_length = len + 8;
|
||||
|
||||
sys$sndopr(opc_dsc, 0);
|
||||
|
||||
OPENSSL_free(opcdef_p);
|
||||
}
|
||||
|
||||
static void xcloselog(BIO *bp)
|
||||
{
|
||||
}
|
||||
|
||||
# else /* Unix/Watt32 */
|
||||
|
||||
static void xopenlog(BIO *bp, char *name, int level)
|
||||
{
|
||||
# ifdef WATT32 /* djgpp/DOS */
|
||||
openlog(name, LOG_PID | LOG_CONS | LOG_NDELAY, level);
|
||||
# else
|
||||
openlog(name, LOG_PID | LOG_CONS, level);
|
||||
# endif
|
||||
}
|
||||
|
||||
static void xsyslog(BIO *bp, int priority, const char *string)
|
||||
{
|
||||
syslog(priority, "%s", string);
|
||||
}
|
||||
|
||||
static void xcloselog(BIO *bp)
|
||||
{
|
||||
closelog();
|
||||
}
|
||||
|
||||
# endif /* Unix */
|
||||
|
||||
#else /* NO_SYSLOG */
|
||||
const BIO_METHOD *BIO_s_log(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif /* NO_SYSLOG */
|
357
trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_mem.c
vendored
Normal file
357
trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_mem.c
vendored
Normal file
|
@ -0,0 +1,357 @@
|
|||
/*
|
||||
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include "bio_lcl.h"
|
||||
#include "internal/cryptlib.h"
|
||||
|
||||
static int mem_write(BIO *h, const char *buf, int num);
|
||||
static int mem_read(BIO *h, char *buf, int size);
|
||||
static int mem_puts(BIO *h, const char *str);
|
||||
static int mem_gets(BIO *h, char *str, int size);
|
||||
static long mem_ctrl(BIO *h, int cmd, long arg1, void *arg2);
|
||||
static int mem_new(BIO *h);
|
||||
static int secmem_new(BIO *h);
|
||||
static int mem_free(BIO *data);
|
||||
static int mem_buf_free(BIO *data);
|
||||
static int mem_buf_sync(BIO *h);
|
||||
|
||||
static const BIO_METHOD mem_method = {
|
||||
BIO_TYPE_MEM,
|
||||
"memory buffer",
|
||||
/* TODO: Convert to new style write function */
|
||||
bwrite_conv,
|
||||
mem_write,
|
||||
/* TODO: Convert to new style read function */
|
||||
bread_conv,
|
||||
mem_read,
|
||||
mem_puts,
|
||||
mem_gets,
|
||||
mem_ctrl,
|
||||
mem_new,
|
||||
mem_free,
|
||||
NULL, /* mem_callback_ctrl */
|
||||
};
|
||||
|
||||
static const BIO_METHOD secmem_method = {
|
||||
BIO_TYPE_MEM,
|
||||
"secure memory buffer",
|
||||
/* TODO: Convert to new style write function */
|
||||
bwrite_conv,
|
||||
mem_write,
|
||||
/* TODO: Convert to new style read function */
|
||||
bread_conv,
|
||||
mem_read,
|
||||
mem_puts,
|
||||
mem_gets,
|
||||
mem_ctrl,
|
||||
secmem_new,
|
||||
mem_free,
|
||||
NULL, /* mem_callback_ctrl */
|
||||
};
|
||||
|
||||
/* BIO memory stores buffer and read pointer */
|
||||
typedef struct bio_buf_mem_st {
|
||||
struct buf_mem_st *buf; /* allocated buffer */
|
||||
struct buf_mem_st *readp; /* read pointer */
|
||||
} BIO_BUF_MEM;
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
const BIO_METHOD *BIO_s_secmem(void)
|
||||
{
|
||||
return(&secmem_method);
|
||||
}
|
||||
|
||||
BIO *BIO_new_mem_buf(const void *buf, int len)
|
||||
{
|
||||
BIO *ret;
|
||||
BUF_MEM *b;
|
||||
BIO_BUF_MEM *bb;
|
||||
size_t sz;
|
||||
|
||||
if (buf == NULL) {
|
||||
BIOerr(BIO_F_BIO_NEW_MEM_BUF, BIO_R_NULL_PARAMETER);
|
||||
return NULL;
|
||||
}
|
||||
sz = (len < 0) ? strlen(buf) : (size_t)len;
|
||||
if ((ret = BIO_new(BIO_s_mem())) == NULL)
|
||||
return NULL;
|
||||
bb = (BIO_BUF_MEM *)ret->ptr;
|
||||
b = bb->buf;
|
||||
/* Cast away const and trust in the MEM_RDONLY flag. */
|
||||
b->data = (void *)buf;
|
||||
b->length = sz;
|
||||
b->max = sz;
|
||||
*bb->readp = *bb->buf;
|
||||
ret->flags |= BIO_FLAGS_MEM_RDONLY;
|
||||
/* Since this is static data retrying won't help */
|
||||
ret->num = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mem_init(BIO *bi, unsigned long flags)
|
||||
{
|
||||
BIO_BUF_MEM *bb = OPENSSL_zalloc(sizeof(*bb));
|
||||
|
||||
if (bb == NULL)
|
||||
return 0;
|
||||
if ((bb->buf = BUF_MEM_new_ex(flags)) == NULL) {
|
||||
OPENSSL_free(bb);
|
||||
return 0;
|
||||
}
|
||||
if ((bb->readp = OPENSSL_zalloc(sizeof(*bb->readp))) == NULL) {
|
||||
BUF_MEM_free(bb->buf);
|
||||
OPENSSL_free(bb);
|
||||
return 0;
|
||||
}
|
||||
*bb->readp = *bb->buf;
|
||||
bi->shutdown = 1;
|
||||
bi->init = 1;
|
||||
bi->num = -1;
|
||||
bi->ptr = (char *)bb;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int mem_new(BIO *bi)
|
||||
{
|
||||
return mem_init(bi, 0L);
|
||||
}
|
||||
|
||||
static int secmem_new(BIO *bi)
|
||||
{
|
||||
return mem_init(bi, BUF_MEM_FLAG_SECURE);
|
||||
}
|
||||
|
||||
static int mem_free(BIO *a)
|
||||
{
|
||||
BIO_BUF_MEM *bb;
|
||||
|
||||
if (a == NULL)
|
||||
return 0;
|
||||
|
||||
bb = (BIO_BUF_MEM *)a->ptr;
|
||||
if (!mem_buf_free(a))
|
||||
return 0;
|
||||
OPENSSL_free(bb->readp);
|
||||
OPENSSL_free(bb);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int mem_buf_free(BIO *a)
|
||||
{
|
||||
if (a == NULL)
|
||||
return 0;
|
||||
|
||||
if (a->shutdown && a->init && a->ptr != NULL) {
|
||||
BIO_BUF_MEM *bb = (BIO_BUF_MEM *)a->ptr;
|
||||
BUF_MEM *b = bb->buf;
|
||||
|
||||
if (a->flags & BIO_FLAGS_MEM_RDONLY)
|
||||
b->data = NULL;
|
||||
BUF_MEM_free(b);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reallocate memory buffer if read pointer differs
|
||||
*/
|
||||
static int mem_buf_sync(BIO *b)
|
||||
{
|
||||
if (b != NULL && b->init != 0 && b->ptr != NULL) {
|
||||
BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr;
|
||||
|
||||
if (bbm->readp->data != bbm->buf->data) {
|
||||
memmove(bbm->buf->data, bbm->readp->data, bbm->readp->length);
|
||||
bbm->buf->length = bbm->readp->length;
|
||||
bbm->readp->data = bbm->buf->data;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mem_read(BIO *b, char *out, int outl)
|
||||
{
|
||||
int ret = -1;
|
||||
BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr;
|
||||
BUF_MEM *bm = bbm->readp;
|
||||
|
||||
BIO_clear_retry_flags(b);
|
||||
ret = (outl >= 0 && (size_t)outl > bm->length) ? (int)bm->length : outl;
|
||||
if ((out != NULL) && (ret > 0)) {
|
||||
memcpy(out, bm->data, ret);
|
||||
bm->length -= ret;
|
||||
bm->data += ret;
|
||||
} else if (bm->length == 0) {
|
||||
ret = b->num;
|
||||
if (ret != 0)
|
||||
BIO_set_retry_read(b);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mem_write(BIO *b, const char *in, int inl)
|
||||
{
|
||||
int ret = -1;
|
||||
int blen;
|
||||
BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr;
|
||||
|
||||
if (in == NULL) {
|
||||
BIOerr(BIO_F_MEM_WRITE, BIO_R_NULL_PARAMETER);
|
||||
goto end;
|
||||
}
|
||||
if (b->flags & BIO_FLAGS_MEM_RDONLY) {
|
||||
BIOerr(BIO_F_MEM_WRITE, BIO_R_WRITE_TO_READ_ONLY_BIO);
|
||||
goto end;
|
||||
}
|
||||
BIO_clear_retry_flags(b);
|
||||
if (inl == 0)
|
||||
return 0;
|
||||
blen = bbm->readp->length;
|
||||
mem_buf_sync(b);
|
||||
if (BUF_MEM_grow_clean(bbm->buf, blen + inl) == 0)
|
||||
goto end;
|
||||
memcpy(bbm->buf->data + blen, in, inl);
|
||||
*bbm->readp = *bbm->buf;
|
||||
ret = inl;
|
||||
end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static long mem_ctrl(BIO *b, int cmd, long num, void *ptr)
|
||||
{
|
||||
long ret = 1;
|
||||
char **pptr;
|
||||
BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr;
|
||||
BUF_MEM *bm;
|
||||
|
||||
switch (cmd) {
|
||||
case BIO_CTRL_RESET:
|
||||
bm = bbm->buf;
|
||||
if (bm->data != NULL) {
|
||||
/* For read only case reset to the start again */
|
||||
if ((b->flags & BIO_FLAGS_MEM_RDONLY) || (b->flags & BIO_FLAGS_NONCLEAR_RST)) {
|
||||
bm->length = bm->max;
|
||||
} else {
|
||||
memset(bm->data, 0, bm->max);
|
||||
bm->length = 0;
|
||||
}
|
||||
*bbm->readp = *bbm->buf;
|
||||
}
|
||||
break;
|
||||
case BIO_CTRL_EOF:
|
||||
bm = bbm->readp;
|
||||
ret = (long)(bm->length == 0);
|
||||
break;
|
||||
case BIO_C_SET_BUF_MEM_EOF_RETURN:
|
||||
b->num = (int)num;
|
||||
break;
|
||||
case BIO_CTRL_INFO:
|
||||
bm = bbm->readp;
|
||||
ret = (long)bm->length;
|
||||
if (ptr != NULL) {
|
||||
pptr = (char **)ptr;
|
||||
*pptr = (char *)&(bm->data[0]);
|
||||
}
|
||||
break;
|
||||
case BIO_C_SET_BUF_MEM:
|
||||
mem_buf_free(b);
|
||||
b->shutdown = (int)num;
|
||||
bbm->buf = ptr;
|
||||
*bbm->readp = *bbm->buf;
|
||||
break;
|
||||
case BIO_C_GET_BUF_MEM_PTR:
|
||||
if (ptr != NULL) {
|
||||
mem_buf_sync(b);
|
||||
bm = bbm->readp;
|
||||
pptr = (char **)ptr;
|
||||
*pptr = (char *)bm;
|
||||
}
|
||||
break;
|
||||
case BIO_CTRL_GET_CLOSE:
|
||||
ret = (long)b->shutdown;
|
||||
break;
|
||||
case BIO_CTRL_SET_CLOSE:
|
||||
b->shutdown = (int)num;
|
||||
break;
|
||||
case BIO_CTRL_WPENDING:
|
||||
ret = 0L;
|
||||
break;
|
||||
case BIO_CTRL_PENDING:
|
||||
bm = bbm->readp;
|
||||
ret = (long)bm->length;
|
||||
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 *bp, char *buf, int size)
|
||||
{
|
||||
int i, j;
|
||||
int ret = -1;
|
||||
char *p;
|
||||
BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)bp->ptr;
|
||||
BUF_MEM *bm = bbm->readp;
|
||||
|
||||
BIO_clear_retry_flags(bp);
|
||||
j = bm->length;
|
||||
if ((size - 1) < j)
|
||||
j = size - 1;
|
||||
if (j <= 0) {
|
||||
*buf = '\0';
|
||||
return 0;
|
||||
}
|
||||
p = bm->data;
|
||||
for (i = 0; i < j; i++) {
|
||||
if (p[i] == '\n') {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* i is now the max num of bytes to copy, either j or up to
|
||||
* and including the first newline
|
||||
*/
|
||||
|
||||
i = mem_read(bp, buf, i);
|
||||
if (i > 0)
|
||||
buf[i] = '\0';
|
||||
ret = i;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mem_puts(BIO *bp, const char *str)
|
||||
{
|
||||
int n, ret;
|
||||
|
||||
n = strlen(str);
|
||||
ret = mem_write(bp, str, n);
|
||||
/* memory semantics is that it will always work */
|
||||
return ret;
|
||||
}
|
87
trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_null.c
vendored
Normal file
87
trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_null.c
vendored
Normal file
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include "bio_lcl.h"
|
||||
#include "internal/cryptlib.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 const BIO_METHOD null_method = {
|
||||
BIO_TYPE_NULL,
|
||||
"NULL",
|
||||
/* TODO: Convert to new style write function */
|
||||
bwrite_conv,
|
||||
null_write,
|
||||
/* TODO: Convert to new style read function */
|
||||
bread_conv,
|
||||
null_read,
|
||||
null_puts,
|
||||
null_gets,
|
||||
null_ctrl,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL, /* null_callback_ctrl */
|
||||
};
|
||||
|
||||
const BIO_METHOD *BIO_s_null(void)
|
||||
{
|
||||
return &null_method;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
233
trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_sock.c
vendored
Normal file
233
trunk/3rdparty/openssl-1.1-fit/crypto/bio/bss_sock.c
vendored
Normal file
|
@ -0,0 +1,233 @@
|
|||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include "bio_lcl.h"
|
||||
#include "internal/cryptlib.h"
|
||||
|
||||
#ifndef OPENSSL_NO_SOCK
|
||||
|
||||
# include <openssl/bio.h>
|
||||
|
||||
# ifdef WATT32
|
||||
/* Watt-32 uses same names */
|
||||
# undef sock_write
|
||||
# undef sock_read
|
||||
# undef sock_puts
|
||||
# define sock_write SockWrite
|
||||
# define sock_read SockRead
|
||||
# define sock_puts SockPuts
|
||||
# endif
|
||||
|
||||
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 = {
|
||||
BIO_TYPE_SOCKET,
|
||||
"socket",
|
||||
/* TODO: Convert to new style write function */
|
||||
bwrite_conv,
|
||||
sock_write,
|
||||
/* TODO: Convert to new style read function */
|
||||
bread_conv,
|
||||
sock_read,
|
||||
sock_puts,
|
||||
NULL, /* sock_gets, */
|
||||
sock_ctrl,
|
||||
sock_new,
|
||||
sock_free,
|
||||
NULL, /* sock_callback_ctrl */
|
||||
};
|
||||
|
||||
const BIO_METHOD *BIO_s_socket(void)
|
||||
{
|
||||
return &methods_sockp;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
BIO_closesocket(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) {
|
||||
clear_socket_error();
|
||||
ret = readsocket(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;
|
||||
|
||||
clear_socket_error();
|
||||
ret = writesocket(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 = get_last_socket_error();
|
||||
|
||||
return BIO_sock_non_fatal_error(err);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int BIO_sock_non_fatal_error(int err)
|
||||
{
|
||||
switch (err) {
|
||||
# if defined(OPENSSL_SYS_WINDOWS)
|
||||
# if defined(WSAEWOULDBLOCK)
|
||||
case WSAEWOULDBLOCK:
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifdef EWOULDBLOCK
|
||||
# ifdef WSAEWOULDBLOCK
|
||||
# if WSAEWOULDBLOCK != EWOULDBLOCK
|
||||
case EWOULDBLOCK:
|
||||
# endif
|
||||
# else
|
||||
case EWOULDBLOCK:
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# if defined(ENOTCONN)
|
||||
case ENOTCONN:
|
||||
# endif
|
||||
|
||||
# ifdef EINTR
|
||||
case EINTR:
|
||||
# endif
|
||||
|
||||
# ifdef EAGAIN
|
||||
# if EWOULDBLOCK != EAGAIN
|
||||
case EAGAIN:
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifdef EPROTO
|
||||
case EPROTO:
|
||||
# endif
|
||||
|
||||
# ifdef EINPROGRESS
|
||||
case EINPROGRESS:
|
||||
# endif
|
||||
|
||||
# ifdef EALREADY
|
||||
case EALREADY:
|
||||
# endif
|
||||
return 1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* #ifndef OPENSSL_NO_SOCK */
|
8
trunk/3rdparty/openssl-1.1-fit/crypto/bio/build.info
vendored
Normal file
8
trunk/3rdparty/openssl-1.1-fit/crypto/bio/build.info
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
LIBS=../../libcrypto
|
||||
SOURCE[../../libcrypto]=\
|
||||
bio_lib.c bio_cb.c bio_err.c \
|
||||
bss_mem.c bss_null.c bss_fd.c \
|
||||
bss_file.c bss_sock.c bss_conn.c \
|
||||
bf_null.c bf_buff.c b_print.c b_dump.c b_addr.c \
|
||||
b_sock.c b_sock2.c bss_acpt.c bf_nbio.c bss_log.c bss_bio.c \
|
||||
bss_dgram.c bio_meth.c bf_lbuf.c
|
Loading…
Add table
Add a link
Reference in a new issue