diff options
author | jkim <jkim@FreeBSD.org> | 2012-07-12 19:30:53 +0000 |
---|---|---|
committer | jkim <jkim@FreeBSD.org> | 2012-07-12 19:30:53 +0000 |
commit | e393e47b1e23744a7d0ed999afb5d137070f5f8f (patch) | |
tree | 9739a803477c4610ec6628d914bdcc55fbb3602a /crypto/openssl/crypto/bio | |
parent | a8b00dea2cde4c3d96e6ed1de530ddff21012266 (diff) | |
parent | 532b4084cb8cac5e6d91d42aa6a497dd4ba4a4f5 (diff) | |
download | FreeBSD-src-e393e47b1e23744a7d0ed999afb5d137070f5f8f.zip FreeBSD-src-e393e47b1e23744a7d0ed999afb5d137070f5f8f.tar.gz |
Merge OpenSSL 1.0.1c.
Approved by: benl (maintainer)
Diffstat (limited to 'crypto/openssl/crypto/bio')
-rw-r--r-- | crypto/openssl/crypto/bio/Makefile | 13 | ||||
-rw-r--r-- | crypto/openssl/crypto/bio/b_print.c | 4 | ||||
-rw-r--r-- | crypto/openssl/crypto/bio/b_sock.c | 266 | ||||
-rw-r--r-- | crypto/openssl/crypto/bio/bio.h | 124 | ||||
-rw-r--r-- | crypto/openssl/crypto/bio/bio_cb.c | 24 | ||||
-rw-r--r-- | crypto/openssl/crypto/bio/bio_err.c | 3 | ||||
-rw-r--r-- | crypto/openssl/crypto/bio/bio_lcl.h | 10 | ||||
-rw-r--r-- | crypto/openssl/crypto/bio/bio_lib.c | 32 | ||||
-rw-r--r-- | crypto/openssl/crypto/bio/bss_acpt.c | 8 | ||||
-rw-r--r-- | crypto/openssl/crypto/bio/bss_bio.c | 18 | ||||
-rw-r--r-- | crypto/openssl/crypto/bio/bss_dgram.c | 1166 | ||||
-rw-r--r-- | crypto/openssl/crypto/bio/bss_fd.c | 27 | ||||
-rw-r--r-- | crypto/openssl/crypto/bio/bss_file.c | 56 | ||||
-rw-r--r-- | crypto/openssl/crypto/bio/bss_log.c | 87 | ||||
-rw-r--r-- | crypto/openssl/crypto/bio/bss_mem.c | 18 |
15 files changed, 1626 insertions, 230 deletions
diff --git a/crypto/openssl/crypto/bio/Makefile b/crypto/openssl/crypto/bio/Makefile index 1cd76ce..c395d80 100644 --- a/crypto/openssl/crypto/bio/Makefile +++ b/crypto/openssl/crypto/bio/Makefile @@ -45,7 +45,7 @@ top: all: lib lib: $(LIBOBJ) - $(ARX) $(LIB) $(LIBOBJ) + $(AR) $(LIB) $(LIBOBJ) $(RANLIB) $(LIB) || echo Never mind. @touch lib @@ -102,11 +102,12 @@ b_print.o: ../../include/openssl/safestack.h ../../include/openssl/stack.h b_print.o: ../../include/openssl/symhacks.h ../cryptlib.h b_print.c b_sock.o: ../../e_os.h ../../include/openssl/bio.h b_sock.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h -b_sock.o: ../../include/openssl/e_os2.h ../../include/openssl/err.h -b_sock.o: ../../include/openssl/lhash.h ../../include/openssl/opensslconf.h -b_sock.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h -b_sock.o: ../../include/openssl/safestack.h ../../include/openssl/stack.h -b_sock.o: ../../include/openssl/symhacks.h ../cryptlib.h b_sock.c +b_sock.o: ../../include/openssl/dso.h ../../include/openssl/e_os2.h +b_sock.o: ../../include/openssl/err.h ../../include/openssl/lhash.h +b_sock.o: ../../include/openssl/opensslconf.h ../../include/openssl/opensslv.h +b_sock.o: ../../include/openssl/ossl_typ.h ../../include/openssl/safestack.h +b_sock.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h +b_sock.o: ../cryptlib.h b_sock.c bf_buff.o: ../../e_os.h ../../include/openssl/bio.h bf_buff.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h bf_buff.o: ../../include/openssl/e_os2.h ../../include/openssl/err.h diff --git a/crypto/openssl/crypto/bio/b_print.c b/crypto/openssl/crypto/bio/b_print.c index 3a87b0e..143a7cf 100644 --- a/crypto/openssl/crypto/bio/b_print.c +++ b/crypto/openssl/crypto/bio/b_print.c @@ -115,8 +115,8 @@ #define LDOUBLE double #endif -#if HAVE_LONG_LONG -# if defined(OPENSSL_SYS_WIN32) && !defined(__GNUC__) +#ifdef HAVE_LONG_LONG +# if defined(_WIN32) && !defined(__GNUC__) # define LLONG __int64 # else # define LLONG long long diff --git a/crypto/openssl/crypto/bio/b_sock.c b/crypto/openssl/crypto/bio/b_sock.c index f0d9cfc..41f958b 100644 --- a/crypto/openssl/crypto/bio/b_sock.c +++ b/crypto/openssl/crypto/bio/b_sock.c @@ -72,11 +72,9 @@ NETDB_DEFINE_CONTEXT #ifndef OPENSSL_NO_SOCK -#ifdef OPENSSL_SYS_WIN16 -#define SOCKET_PROTOCOL 0 /* more microsoft stupidity */ -#else +#include <openssl/dso.h> + #define SOCKET_PROTOCOL IPPROTO_TCP -#endif #ifdef SO_MAXCONN #define MAX_LISTEN SO_MAXCONN @@ -90,6 +88,17 @@ NETDB_DEFINE_CONTEXT static int wsa_init_done=0; #endif +/* + * WSAAPI specifier is required to make indirect calls to run-time + * linked WinSock 2 functions used in this module, to be specific + * [get|free]addrinfo and getnameinfo. This is because WinSock uses + * uses non-C calling convention, __stdcall vs. __cdecl, on x86 + * Windows. On non-WinSock platforms WSAAPI needs to be void. + */ +#ifndef WSAAPI +#define WSAAPI +#endif + #if 0 static unsigned long BIO_ghbn_hits=0L; static unsigned long BIO_ghbn_miss=0L; @@ -226,6 +235,10 @@ int BIO_sock_error(int sock) int j,i; int size; +#if defined(OPENSSL_SYS_BEOS_R5) + return 0; +#endif + size=sizeof(int); /* Note: under Windows the third parameter is of type (char *) * whereas under other systems it is (void *) if you don't have @@ -466,7 +479,12 @@ int BIO_sock_init(void) wsa_init_done=1; memset(&wsa_state,0,sizeof(wsa_state)); - if (WSAStartup(0x0101,&wsa_state)!=0) + /* Not making wsa_state available to the rest of the + * code is formally wrong. But the structures we use + * are [beleived 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); @@ -510,8 +528,8 @@ void BIO_sock_cleanup(void) if (wsa_init_done) { wsa_init_done=0; -#ifndef OPENSSL_SYS_WINCE - WSACancelBlockingCall(); /* Winsock 1.1 specific */ +#if 0 /* this call is claimed to be non-present in Winsock2 */ + WSACancelBlockingCall(); #endif WSACleanup(); } @@ -533,7 +551,30 @@ int BIO_socket_ioctl(int fd, long type, void *arg) #ifdef __DJGPP__ i=ioctlsocket(fd,type,(char *)arg); #else - i=ioctlsocket(fd,type,arg); +# 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()); @@ -581,12 +622,18 @@ static int get_ip(const char *str, unsigned char ip[4]) int BIO_get_accept_socket(char *host, int bind_mode) { int ret=0; - struct sockaddr_in server,client; - int s=INVALID_SOCKET,cs; + union { + struct sockaddr sa; + struct sockaddr_in sa_in; +#if OPENSSL_USE_IPV6 + struct sockaddr_in6 sa_in6; +#endif + } server,client; + int s=INVALID_SOCKET,cs,addrlen; unsigned char ip[4]; unsigned short port; char *str=NULL,*e; - const char *h,*p; + char *h,*p; unsigned long l; int err_num; @@ -600,8 +647,7 @@ int BIO_get_accept_socket(char *host, int bind_mode) { if (*e == ':') { - p= &(e[1]); - *e='\0'; + p=e; } else if (*e == '/') { @@ -609,21 +655,74 @@ int BIO_get_accept_socket(char *host, int bind_mode) break; } } - - if (p == NULL) + if (p) *p++='\0'; /* points at last ':', '::port' is special [see below] */ + else p=h,h=NULL; + +#ifdef EAI_FAMILY + do { + static union { void *p; + int (WSAAPI *f)(const char *,const char *, + const struct addrinfo *, + struct addrinfo **); + } p_getaddrinfo = {NULL}; + static union { void *p; + void (WSAAPI *f)(struct addrinfo *); + } p_freeaddrinfo = {NULL}; + struct addrinfo *res,hint; + + if (p_getaddrinfo.p==NULL) + { + if ((p_getaddrinfo.p=DSO_global_lookup("getaddrinfo"))==NULL || + (p_freeaddrinfo.p=DSO_global_lookup("freeaddrinfo"))==NULL) + p_getaddrinfo.p=(void*)-1; + } + if (p_getaddrinfo.p==(void *)-1) break; + + /* '::port' enforces IPv6 wildcard listener. Some OSes, + * e.g. Solaris, default to IPv6 without any hint. Also + * note that commonly IPv6 wildchard socket can service + * IPv4 connections just as well... */ + memset(&hint,0,sizeof(hint)); + hint.ai_flags = AI_PASSIVE; + if (h) { - p=h; - h="*"; + if (strchr(h,':')) + { + if (h[1]=='\0') h=NULL; +#if OPENSSL_USE_IPV6 + hint.ai_family = AF_INET6; +#else + h=NULL; +#endif + } + else if (h[0]=='*' && h[1]=='\0') + { + hint.ai_family = AF_INET; + h=NULL; + } } + if ((*p_getaddrinfo.f)(h,p,&hint,&res)) break; + + addrlen = res->ai_addrlen<=sizeof(server) ? + res->ai_addrlen : + sizeof(server); + memcpy(&server, res->ai_addr, addrlen); + + (*p_freeaddrinfo.f)(res); + goto again; + } while (0); +#endif + if (!BIO_get_port(p,&port)) goto err; memset((char *)&server,0,sizeof(server)); - server.sin_family=AF_INET; - server.sin_port=htons(port); + server.sa_in.sin_family=AF_INET; + server.sa_in.sin_port=htons(port); + addrlen = sizeof(server.sa_in); - if (strcmp(h,"*") == 0) - server.sin_addr.s_addr=INADDR_ANY; + if (h == NULL || strcmp(h,"*") == 0) + server.sa_in.sin_addr.s_addr=INADDR_ANY; else { if (!BIO_get_host_ip(h,&(ip[0]))) goto err; @@ -632,11 +731,11 @@ int BIO_get_accept_socket(char *host, int bind_mode) ((unsigned long)ip[1]<<16L)| ((unsigned long)ip[2]<< 8L)| ((unsigned long)ip[3]); - server.sin_addr.s_addr=htonl(l); + server.sa_in.sin_addr.s_addr=htonl(l); } again: - s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL); + s=socket(server.sa.sa_family,SOCK_STREAM,SOCKET_PROTOCOL); if (s == INVALID_SOCKET) { SYSerr(SYS_F_SOCKET,get_last_socket_error()); @@ -654,7 +753,7 @@ again: bind_mode=BIO_BIND_NORMAL; } #endif - if (bind(s,(struct sockaddr *)&server,sizeof(server)) == -1) + if (bind(s,&server.sa,addrlen) == -1) { #ifdef SO_REUSEADDR err_num=get_last_socket_error(); @@ -668,15 +767,28 @@ again: (err_num == EADDRINUSE)) #endif { - memcpy((char *)&client,(char *)&server,sizeof(server)); - if (strcmp(h,"*") == 0) - client.sin_addr.s_addr=htonl(0x7F000001); - cs=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL); + client = server; + if (h == NULL || strcmp(h,"*") == 0) + { +#if OPENSSL_USE_IPV6 + if (client.sa.sa_family == AF_INET6) + { + memset(&client.sa_in6.sin6_addr,0,sizeof(client.sa_in6.sin6_addr)); + client.sa_in6.sin6_addr.s6_addr[15]=1; + } + else +#endif + if (client.sa.sa_family == AF_INET) + { + client.sa_in.sin_addr.s_addr=htonl(0x7F000001); + } + else goto err; + } + cs=socket(client.sa.sa_family,SOCK_STREAM,SOCKET_PROTOCOL); if (cs != INVALID_SOCKET) { int ii; - ii=connect(cs,(struct sockaddr *)&client, - sizeof(client)); + ii=connect(cs,&client.sa,addrlen); closesocket(cs); if (ii == INVALID_SOCKET) { @@ -715,20 +827,52 @@ err: int BIO_accept(int sock, char **addr) { int ret=INVALID_SOCKET; - static struct sockaddr_in from; unsigned long l; unsigned short port; - int len; char *p; - memset((char *)&from,0,sizeof(from)); - len=sizeof(from); - /* Note: under VMS with SOCKETSHR the fourth parameter is currently - * of type (int *) 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 (int *) or (void *). + struct { + /* + * As for following union. Trouble is that there are platforms + * that have socklen_t and there are platforms that don't, on + * some platforms socklen_t is int and on some size_t. So what + * one can do? One can cook #ifdef spaghetti, which is nothing + * but masochistic. Or one can do union between int and size_t. + * One naturally does it primarily for 64-bit platforms where + * sizeof(int) != sizeof(size_t). But would it work? Note that + * if size_t member is initialized to 0, then later int member + * assignment naturally does the job on little-endian platforms + * regardless accept's expectations! What about big-endians? + * If accept expects int*, then it works, and if size_t*, then + * length value would appear as unreasonably large. But this + * won't prevent it from filling in the address structure. The + * trouble of course would be if accept returns more data than + * actual buffer can accomodate and overwrite stack... That's + * where early OPENSSL_assert comes into picture. Besides, the + * only 64-bit big-endian platform found so far that expects + * size_t* is HP-UX, where stack grows towards higher address. + * <appro> */ - ret=accept(sock,(struct sockaddr *)&from,(void *)&len); + union { size_t s; int i; } len; + union { + struct sockaddr sa; + struct sockaddr_in sa_in; +#if OPENSSL_USE_IPV6 + struct sockaddr_in6 sa_in6; +#endif + } from; + } sa; + + sa.len.s=0; + sa.len.i=sizeof(sa.from); + memset(&sa.from,0,sizeof(sa.from)); + ret=accept(sock,&sa.from.sa,(void *)&sa.len); + if (sizeof(sa.len.i)!=sizeof(sa.len.s) && sa.len.i==0) + { + OPENSSL_assert(sa.len.s<=sizeof(sa.from)); + sa.len.i = (int)sa.len.s; + /* use sa.len.i from this point */ + } if (ret == INVALID_SOCKET) { if(BIO_sock_should_retry(ret)) return -2; @@ -739,8 +883,46 @@ int BIO_accept(int sock, char **addr) if (addr == NULL) goto end; - l=ntohl(from.sin_addr.s_addr); - port=ntohs(from.sin_port); +#ifdef EAI_FAMILY + do { + char h[NI_MAXHOST],s[NI_MAXSERV]; + size_t nl; + static union { void *p; + int (WSAAPI *f)(const struct sockaddr *,size_t/*socklen_t*/, + char *,size_t,char *,size_t,int); + } p_getnameinfo = {NULL}; + /* 2nd argument to getnameinfo is specified to + * be socklen_t. Unfortunately there is a number + * of environments where socklen_t is not defined. + * As it's passed by value, it's safe to pass it + * as size_t... <appro> */ + + if (p_getnameinfo.p==NULL) + { + if ((p_getnameinfo.p=DSO_global_lookup("getnameinfo"))==NULL) + p_getnameinfo.p=(void*)-1; + } + if (p_getnameinfo.p==(void *)-1) break; + + if ((*p_getnameinfo.f)(&sa.from.sa,sa.len.i,h,sizeof(h),s,sizeof(s), + NI_NUMERICHOST|NI_NUMERICSERV)) break; + nl = strlen(h)+strlen(s)+2; + p = *addr; + if (p) { *p = '\0'; p = OPENSSL_realloc(p,nl); } + else { p = OPENSSL_malloc(nl); } + if (p==NULL) + { + BIOerr(BIO_F_BIO_ACCEPT,ERR_R_MALLOC_FAILURE); + goto end; + } + *addr = p; + BIO_snprintf(*addr,nl,"%s:%s",h,s); + goto end; + } while(0); +#endif + if (sa.from.sa.sa_family != AF_INET) goto end; + l=ntohl(sa.from.sa_in.sin_addr.s_addr); + port=ntohs(sa.from.sa_in.sin_port); if (*addr == NULL) { if ((p=OPENSSL_malloc(24)) == NULL) @@ -778,7 +960,6 @@ int BIO_set_tcp_ndelay(int s, int on) #endif return(ret == 0); } -#endif int BIO_socket_nbio(int s, int mode) { @@ -791,3 +972,4 @@ int BIO_socket_nbio(int s, int mode) #endif return(ret == 0); } +#endif diff --git a/crypto/openssl/crypto/bio/bio.h b/crypto/openssl/crypto/bio/bio.h index 03bd3b2..05699ab 100644 --- a/crypto/openssl/crypto/bio/bio.h +++ b/crypto/openssl/crypto/bio/bio.h @@ -68,6 +68,14 @@ #include <openssl/crypto.h> +#ifndef OPENSSL_NO_SCTP +# ifndef OPENSSL_SYS_VMS +# include <stdint.h> +# else +# include <inttypes.h> +# endif +#endif + #ifdef __cplusplus extern "C" { #endif @@ -95,6 +103,10 @@ extern "C" { #define BIO_TYPE_BIO (19|0x0400) /* (half a) BIO pair */ #define BIO_TYPE_LINEBUFFER (20|0x0200) /* filter */ #define BIO_TYPE_DGRAM (21|0x0400|0x0100) +#ifndef OPENSSL_NO_SCTP +#define BIO_TYPE_DGRAM_SCTP (24|0x0400|0x0100) +#endif +#define BIO_TYPE_ASN1 (22|0x0200) /* filter */ #define BIO_TYPE_COMP (23|0x0200) /* filter */ #define BIO_TYPE_DESCRIPTOR 0x0100 /* socket, fd, connect or accept */ @@ -161,7 +173,22 @@ extern "C" { #define BIO_CTRL_DGRAM_SET_PEER 44 /* Destination for the data */ #define BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT 45 /* Next DTLS handshake timeout to - * adjust socket timeouts */ + * adjust socket timeouts */ + +#ifndef OPENSSL_NO_SCTP +/* SCTP stuff */ +#define BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE 50 +#define BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY 51 +#define BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY 52 +#define BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD 53 +#define BIO_CTRL_DGRAM_SCTP_GET_SNDINFO 60 +#define BIO_CTRL_DGRAM_SCTP_SET_SNDINFO 61 +#define BIO_CTRL_DGRAM_SCTP_GET_RCVINFO 62 +#define BIO_CTRL_DGRAM_SCTP_SET_RCVINFO 63 +#define BIO_CTRL_DGRAM_SCTP_GET_PRINFO 64 +#define BIO_CTRL_DGRAM_SCTP_SET_PRINFO 65 +#define BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN 70 +#endif /* modifiers */ #define BIO_FP_READ 0x02 @@ -266,7 +293,6 @@ int BIO_method_type(const BIO *b); typedef void bio_info_cb(struct bio_st *, int, const char *, int, long, long); -#ifndef OPENSSL_SYS_WIN16 typedef struct bio_method_st { int type; @@ -280,21 +306,6 @@ typedef struct bio_method_st int (*destroy)(BIO *); long (*callback_ctrl)(BIO *, int, bio_info_cb *); } BIO_METHOD; -#else -typedef struct bio_method_st - { - int type; - const char *name; - int (_far *bwrite)(); - int (_far *bread)(); - int (_far *bputs)(); - int (_far *bgets)(); - long (_far *ctrl)(); - int (_far *create)(); - int (_far *destroy)(); - long (_far *callback_ctrl)(); - } BIO_METHOD; -#endif struct bio_st { @@ -344,6 +355,37 @@ typedef struct bio_f_buffer_ctx_struct int obuf_off; /* write/read offset */ } BIO_F_BUFFER_CTX; +/* Prefix and suffix callback in ASN1 BIO */ +typedef int asn1_ps_func(BIO *b, unsigned char **pbuf, int *plen, void *parg); + +#ifndef OPENSSL_NO_SCTP +/* SCTP parameter structs */ +struct bio_dgram_sctp_sndinfo + { + uint16_t snd_sid; + uint16_t snd_flags; + uint32_t snd_ppid; + uint32_t snd_context; + }; + +struct bio_dgram_sctp_rcvinfo + { + uint16_t rcv_sid; + uint16_t rcv_ssn; + uint16_t rcv_flags; + uint32_t rcv_ppid; + uint32_t rcv_tsn; + uint32_t rcv_cumtsn; + uint32_t rcv_context; + }; + +struct bio_dgram_sctp_prinfo + { + uint16_t pr_policy; + uint32_t pr_value; + }; +#endif + /* connect BIO stuff */ #define BIO_CONN_S_BEFORE 1 #define BIO_CONN_S_GET_IP 2 @@ -406,6 +448,13 @@ typedef struct bio_f_buffer_ctx_struct #define BIO_C_RESET_READ_REQUEST 147 #define BIO_C_SET_MD_CTX 148 +#define BIO_C_SET_PREFIX 149 +#define BIO_C_GET_PREFIX 150 +#define BIO_C_SET_SUFFIX 151 +#define BIO_C_GET_SUFFIX 152 + +#define BIO_C_SET_EX_ARG 153 +#define BIO_C_GET_EX_ARG 154 #define BIO_set_app_data(s,arg) BIO_set_ex_data(s,0,arg) #define BIO_get_app_data(s) BIO_get_ex_data(s,0) @@ -569,22 +618,21 @@ int BIO_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, unsigned long BIO_number_read(BIO *bio); unsigned long BIO_number_written(BIO *bio); +/* For BIO_f_asn1() */ +int BIO_asn1_set_prefix(BIO *b, asn1_ps_func *prefix, + asn1_ps_func *prefix_free); +int BIO_asn1_get_prefix(BIO *b, asn1_ps_func **pprefix, + asn1_ps_func **pprefix_free); +int BIO_asn1_set_suffix(BIO *b, asn1_ps_func *suffix, + asn1_ps_func *suffix_free); +int BIO_asn1_get_suffix(BIO *b, asn1_ps_func **psuffix, + asn1_ps_func **psuffix_free); + # ifndef OPENSSL_NO_FP_API -# if defined(OPENSSL_SYS_WIN16) && defined(_WINDLL) -BIO_METHOD *BIO_s_file_internal(void); -BIO *BIO_new_file_internal(char *filename, char *mode); -BIO *BIO_new_fp_internal(FILE *stream, int close_flag); -# define BIO_s_file BIO_s_file_internal -# define BIO_new_file BIO_new_file_internal -# define BIO_new_fp BIO_new_fp_internal -# else /* FP_API */ BIO_METHOD *BIO_s_file(void ); BIO *BIO_new_file(const char *filename, const char *mode); BIO *BIO_new_fp(FILE *stream, int close_flag); -# define BIO_s_file_internal BIO_s_file -# define BIO_new_file_internal BIO_new_file -# define BIO_new_fp_internal BIO_s_file -# endif /* FP_API */ +# define BIO_s_file_internal BIO_s_file # endif BIO * BIO_new(BIO_METHOD *type); int BIO_set(BIO *a,BIO_METHOD *type); @@ -613,13 +661,8 @@ int BIO_nread(BIO *bio, char **buf, int num); int BIO_nwrite0(BIO *bio, char **buf); int BIO_nwrite(BIO *bio, char **buf, int num); -#ifndef OPENSSL_SYS_WIN16 long BIO_debug_callback(BIO *bio,int cmd,const char *argp,int argi, long argl,long ret); -#else -long _far _loadds BIO_debug_callback(BIO *bio,int cmd,const char *argp,int argi, - long argl,long ret); -#endif BIO_METHOD *BIO_s_mem(void); BIO *BIO_new_mem_buf(void *buf, int len); @@ -640,6 +683,9 @@ BIO_METHOD *BIO_f_linebuffer(void); BIO_METHOD *BIO_f_nbio_test(void); #ifndef OPENSSL_NO_DGRAM BIO_METHOD *BIO_s_datagram(void); +#ifndef OPENSSL_NO_SCTP +BIO_METHOD *BIO_s_datagram_sctp(void); +#endif #endif /* BIO_METHOD *BIO_f_ber(void); */ @@ -682,6 +728,15 @@ int BIO_set_tcp_ndelay(int sock,int turn_on); BIO *BIO_new_socket(int sock, int close_flag); BIO *BIO_new_dgram(int fd, int close_flag); +#ifndef OPENSSL_NO_SCTP +BIO *BIO_new_dgram_sctp(int fd, int close_flag); +int BIO_dgram_is_sctp(BIO *bio); +int BIO_dgram_sctp_notification_cb(BIO *b, + void (*handle_notifications)(BIO *bio, void *context, void *buf), + void *context); +int BIO_dgram_sctp_wait_for_dry(BIO *b); +int BIO_dgram_sctp_msg_waiting(BIO *b); +#endif BIO *BIO_new_fd(int fd, int close_flag); BIO *BIO_new_connect(char *host_port); BIO *BIO_new_accept(char *host_port); @@ -746,6 +801,7 @@ void ERR_load_BIO_strings(void); #define BIO_F_BUFFER_CTRL 114 #define BIO_F_CONN_CTRL 127 #define BIO_F_CONN_STATE 115 +#define BIO_F_DGRAM_SCTP_READ 132 #define BIO_F_FILE_CTRL 116 #define BIO_F_FILE_READ 130 #define BIO_F_LINEBUFFER_CTRL 129 diff --git a/crypto/openssl/crypto/bio/bio_cb.c b/crypto/openssl/crypto/bio/bio_cb.c index 6f4254a..9bcbc32 100644 --- a/crypto/openssl/crypto/bio/bio_cb.c +++ b/crypto/openssl/crypto/bio/bio_cb.c @@ -85,28 +85,32 @@ long MS_CALLBACK BIO_debug_callback(BIO *bio, int cmd, const char *argp, break; case BIO_CB_READ: if (bio->method->type & BIO_TYPE_DESCRIPTOR) - BIO_snprintf(p,p_maxlen,"read(%d,%d) - %s fd=%d\n", - bio->num,argi,bio->method->name,bio->num); + BIO_snprintf(p,p_maxlen,"read(%d,%lu) - %s fd=%d\n", + bio->num,(unsigned long)argi, + bio->method->name,bio->num); else - BIO_snprintf(p,p_maxlen,"read(%d,%d) - %s\n", - bio->num,argi,bio->method->name); + BIO_snprintf(p,p_maxlen,"read(%d,%lu) - %s\n", + bio->num,(unsigned long)argi, + bio->method->name); break; case BIO_CB_WRITE: if (bio->method->type & BIO_TYPE_DESCRIPTOR) - BIO_snprintf(p,p_maxlen,"write(%d,%d) - %s fd=%d\n", - bio->num,argi,bio->method->name,bio->num); + BIO_snprintf(p,p_maxlen,"write(%d,%lu) - %s fd=%d\n", + bio->num,(unsigned long)argi, + bio->method->name,bio->num); else - BIO_snprintf(p,p_maxlen,"write(%d,%d) - %s\n", - bio->num,argi,bio->method->name); + BIO_snprintf(p,p_maxlen,"write(%d,%lu) - %s\n", + bio->num,(unsigned long)argi, + bio->method->name); break; case BIO_CB_PUTS: BIO_snprintf(p,p_maxlen,"puts() - %s\n",bio->method->name); break; case BIO_CB_GETS: - BIO_snprintf(p,p_maxlen,"gets(%d) - %s\n",argi,bio->method->name); + BIO_snprintf(p,p_maxlen,"gets(%lu) - %s\n",(unsigned long)argi,bio->method->name); break; case BIO_CB_CTRL: - BIO_snprintf(p,p_maxlen,"ctrl(%d) - %s\n",argi,bio->method->name); + BIO_snprintf(p,p_maxlen,"ctrl(%lu) - %s\n",(unsigned long)argi,bio->method->name); break; case BIO_CB_RETURN|BIO_CB_READ: BIO_snprintf(p,p_maxlen,"read return %ld\n",ret); diff --git a/crypto/openssl/crypto/bio/bio_err.c b/crypto/openssl/crypto/bio/bio_err.c index 6603f1c..0dbfbd8 100644 --- a/crypto/openssl/crypto/bio/bio_err.c +++ b/crypto/openssl/crypto/bio/bio_err.c @@ -1,6 +1,6 @@ /* crypto/bio/bio_err.c */ /* ==================================================================== - * Copyright (c) 1999-2005 The OpenSSL Project. All rights reserved. + * Copyright (c) 1999-2011 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -95,6 +95,7 @@ static ERR_STRING_DATA BIO_str_functs[]= {ERR_FUNC(BIO_F_BUFFER_CTRL), "BUFFER_CTRL"}, {ERR_FUNC(BIO_F_CONN_CTRL), "CONN_CTRL"}, {ERR_FUNC(BIO_F_CONN_STATE), "CONN_STATE"}, +{ERR_FUNC(BIO_F_DGRAM_SCTP_READ), "DGRAM_SCTP_READ"}, {ERR_FUNC(BIO_F_FILE_CTRL), "FILE_CTRL"}, {ERR_FUNC(BIO_F_FILE_READ), "FILE_READ"}, {ERR_FUNC(BIO_F_LINEBUFFER_CTRL), "LINEBUFFER_CTRL"}, diff --git a/crypto/openssl/crypto/bio/bio_lcl.h b/crypto/openssl/crypto/bio/bio_lcl.h index dba2919..e7f7ec8 100644 --- a/crypto/openssl/crypto/bio/bio_lcl.h +++ b/crypto/openssl/crypto/bio/bio_lcl.h @@ -18,11 +18,19 @@ #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 diff --git a/crypto/openssl/crypto/bio/bio_lib.c b/crypto/openssl/crypto/bio/bio_lib.c index 371cdf5..9c9646a 100644 --- a/crypto/openssl/crypto/bio/bio_lib.c +++ b/crypto/openssl/crypto/bio/bio_lib.c @@ -429,7 +429,7 @@ BIO *BIO_push(BIO *b, BIO *bio) if (bio != NULL) bio->prev_bio=lb; /* called to do internal processing */ - BIO_ctrl(b,BIO_CTRL_PUSH,0,NULL); + BIO_ctrl(b,BIO_CTRL_PUSH,0,lb); return(b); } @@ -441,7 +441,7 @@ BIO *BIO_pop(BIO *b) if (b == NULL) return(NULL); ret=b->next_bio; - BIO_ctrl(b,BIO_CTRL_POP,0,NULL); + BIO_ctrl(b,BIO_CTRL_POP,0,b); if (b->prev_bio != NULL) b->prev_bio->next_bio=b->next_bio; @@ -521,40 +521,40 @@ void BIO_free_all(BIO *bio) BIO *BIO_dup_chain(BIO *in) { - BIO *ret=NULL,*eoc=NULL,*bio,*new; + BIO *ret=NULL,*eoc=NULL,*bio,*new_bio; for (bio=in; bio != NULL; bio=bio->next_bio) { - if ((new=BIO_new(bio->method)) == NULL) goto err; - new->callback=bio->callback; - new->cb_arg=bio->cb_arg; - new->init=bio->init; - new->shutdown=bio->shutdown; - new->flags=bio->flags; + if ((new_bio=BIO_new(bio->method)) == NULL) goto err; + new_bio->callback=bio->callback; + 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->num=bio->num; + new_bio->num=bio->num; - if (!BIO_dup_state(bio,(char *)new)) + if (!BIO_dup_state(bio,(char *)new_bio)) { - BIO_free(new); + BIO_free(new_bio); goto err; } /* copy app data */ - if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_BIO, &new->ex_data, + if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_BIO, &new_bio->ex_data, &bio->ex_data)) goto err; if (ret == NULL) { - eoc=new; + eoc=new_bio; ret=eoc; } else { - BIO_push(eoc,new); - eoc=new; + BIO_push(eoc,new_bio); + eoc=new_bio; } } return(ret); diff --git a/crypto/openssl/crypto/bio/bss_acpt.c b/crypto/openssl/crypto/bio/bss_acpt.c index e7fb892..5d49e1a 100644 --- a/crypto/openssl/crypto/bio/bss_acpt.c +++ b/crypto/openssl/crypto/bio/bss_acpt.c @@ -100,8 +100,8 @@ 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); -BIO_ACCEPT *BIO_ACCEPT_new(void ); -void BIO_ACCEPT_free(BIO_ACCEPT *a); +static BIO_ACCEPT *BIO_ACCEPT_new(void ); +static void BIO_ACCEPT_free(BIO_ACCEPT *a); #define ACPT_S_BEFORE 1 #define ACPT_S_GET_ACCEPT_SOCKET 2 @@ -141,7 +141,7 @@ static int acpt_new(BIO *bi) return(1); } -BIO_ACCEPT *BIO_ACCEPT_new(void) +static BIO_ACCEPT *BIO_ACCEPT_new(void) { BIO_ACCEPT *ret; @@ -154,7 +154,7 @@ BIO_ACCEPT *BIO_ACCEPT_new(void) return(ret); } -void BIO_ACCEPT_free(BIO_ACCEPT *a) +static void BIO_ACCEPT_free(BIO_ACCEPT *a) { if(a == NULL) return; diff --git a/crypto/openssl/crypto/bio/bss_bio.c b/crypto/openssl/crypto/bio/bss_bio.c index 76bd48e..52ef0eb 100644 --- a/crypto/openssl/crypto/bio/bss_bio.c +++ b/crypto/openssl/crypto/bio/bss_bio.c @@ -277,10 +277,10 @@ static int bio_read(BIO *bio, char *buf, int size_) */ /* WARNING: The non-copying interface is largely untested as of yet * and may contain bugs. */ -static ssize_t bio_nread0(BIO *bio, char **buf) +static ossl_ssize_t bio_nread0(BIO *bio, char **buf) { struct bio_bio_st *b, *peer_b; - ssize_t num; + ossl_ssize_t num; BIO_clear_retry_flags(bio); @@ -315,15 +315,15 @@ static ssize_t bio_nread0(BIO *bio, char **buf) return num; } -static ssize_t bio_nread(BIO *bio, char **buf, size_t num_) +static ossl_ssize_t bio_nread(BIO *bio, char **buf, size_t num_) { struct bio_bio_st *b, *peer_b; - ssize_t num, available; + ossl_ssize_t num, available; if (num_ > SSIZE_MAX) num = SSIZE_MAX; else - num = (ssize_t)num_; + num = (ossl_ssize_t)num_; available = bio_nread0(bio, buf); if (num > available) @@ -428,7 +428,7 @@ static int bio_write(BIO *bio, const char *buf, int num_) * (example usage: bio_nwrite0(), write to buffer, bio_nwrite() * or just bio_nwrite(), write to buffer) */ -static ssize_t bio_nwrite0(BIO *bio, char **buf) +static ossl_ssize_t bio_nwrite0(BIO *bio, char **buf) { struct bio_bio_st *b; size_t num; @@ -476,15 +476,15 @@ static ssize_t bio_nwrite0(BIO *bio, char **buf) return num; } -static ssize_t bio_nwrite(BIO *bio, char **buf, size_t num_) +static ossl_ssize_t bio_nwrite(BIO *bio, char **buf, size_t num_) { struct bio_bio_st *b; - ssize_t num, space; + ossl_ssize_t num, space; if (num_ > SSIZE_MAX) num = SSIZE_MAX; else - num = (ssize_t)num_; + num = (ossl_ssize_t)num_; space = bio_nwrite0(bio, buf); if (num > space) diff --git a/crypto/openssl/crypto/bio/bss_dgram.c b/crypto/openssl/crypto/bio/bss_dgram.c index e0327bd..1b1e4be 100644 --- a/crypto/openssl/crypto/bio/bss_dgram.c +++ b/crypto/openssl/crypto/bio/bss_dgram.c @@ -70,6 +70,13 @@ #include <sys/timeb.h> #endif +#ifndef OPENSSL_NO_SCTP +#include <netinet/sctp.h> +#include <fcntl.h> +#define OPENSSL_SCTP_DATA_CHUNK_TYPE 0x00 +#define OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE 0xc0 +#endif + #ifdef OPENSSL_SYS_LINUX #define IP_MTU 14 /* linux is lame */ #endif @@ -88,6 +95,18 @@ static int dgram_new(BIO *h); static int dgram_free(BIO *data); static int dgram_clear(BIO *bio); +#ifndef OPENSSL_NO_SCTP +static int dgram_sctp_write(BIO *h, const char *buf, int num); +static int dgram_sctp_read(BIO *h, char *buf, int size); +static int dgram_sctp_puts(BIO *h, const char *str); +static long dgram_sctp_ctrl(BIO *h, int cmd, long arg1, void *arg2); +static int dgram_sctp_new(BIO *h); +static int dgram_sctp_free(BIO *data); +#ifdef SCTP_AUTHENTICATION_EVENT +static void dgram_sctp_handle_auth_free_key_event(BIO *b, union sctp_notification *snp); +#endif +#endif + static int BIO_dgram_should_retry(int s); static void get_current_time(struct timeval *t); @@ -106,9 +125,31 @@ static BIO_METHOD methods_dgramp= NULL, }; +#ifndef OPENSSL_NO_SCTP +static BIO_METHOD methods_dgramp_sctp= + { + BIO_TYPE_DGRAM_SCTP, + "datagram sctp socket", + dgram_sctp_write, + dgram_sctp_read, + dgram_sctp_puts, + NULL, /* dgram_gets, */ + dgram_sctp_ctrl, + dgram_sctp_new, + dgram_sctp_free, + NULL, + }; +#endif + typedef struct bio_dgram_data_st { - struct sockaddr peer; + union { + struct sockaddr sa; + struct sockaddr_in sa_in; +#if OPENSSL_USE_IPV6 + struct sockaddr_in6 sa_in6; +#endif + } peer; unsigned int connected; unsigned int _errno; unsigned int mtu; @@ -116,6 +157,40 @@ typedef struct bio_dgram_data_st struct timeval socket_timeout; } bio_dgram_data; +#ifndef OPENSSL_NO_SCTP +typedef struct bio_dgram_sctp_save_message_st + { + BIO *bio; + char *data; + int length; + } bio_dgram_sctp_save_message; + +typedef struct bio_dgram_sctp_data_st + { + union { + struct sockaddr sa; + struct sockaddr_in sa_in; +#if OPENSSL_USE_IPV6 + struct sockaddr_in6 sa_in6; +#endif + } peer; + unsigned int connected; + unsigned int _errno; + unsigned int mtu; + struct bio_dgram_sctp_sndinfo sndinfo; + struct bio_dgram_sctp_rcvinfo rcvinfo; + struct bio_dgram_sctp_prinfo prinfo; + void (*handle_notifications)(BIO *bio, void *context, void *buf); + void* notification_context; + int in_handshake; + int ccs_rcvd; + int ccs_sent; + int save_shutdown; + int peer_auth_tested; + bio_dgram_sctp_save_message saved_message; + } bio_dgram_sctp_data; +#endif + BIO_METHOD *BIO_s_datagram(void) { return(&methods_dgramp); @@ -274,23 +349,37 @@ static int dgram_read(BIO *b, char *out, int outl) int ret=0; bio_dgram_data *data = (bio_dgram_data *)b->ptr; - struct sockaddr peer; - int peerlen = sizeof(peer); + struct { + /* + * See commentary in b_sock.c. <appro> + */ + union { size_t s; int i; } len; + union { + struct sockaddr sa; + struct sockaddr_in sa_in; +#if OPENSSL_USE_IPV6 + struct sockaddr_in6 sa_in6; +#endif + } peer; + } sa; + + sa.len.s=0; + sa.len.i=sizeof(sa.peer); if (out != NULL) { clear_socket_error(); - memset(&peer, 0x00, peerlen); - /* Last arg in recvfrom is signed on some platforms and - * unsigned on others. It is of type socklen_t on some - * but this is not universal. Cast to (void *) to avoid - * compiler warnings. - */ + memset(&sa.peer, 0x00, sizeof(sa.peer)); dgram_adjust_rcv_timeout(b); - ret=recvfrom(b->num,out,outl,0,&peer,(void *)&peerlen); + ret=recvfrom(b->num,out,outl,0,&sa.peer.sa,(void *)&sa.len); + if (sizeof(sa.len.i)!=sizeof(sa.len.s) && sa.len.i==0) + { + OPENSSL_assert(sa.len.s<=sizeof(sa.peer)); + sa.len.i = (int)sa.len.s; + } if ( ! data->connected && ret >= 0) - BIO_ctrl(b, BIO_CTRL_DGRAM_SET_PEER, 0, &peer); + BIO_ctrl(b, BIO_CTRL_DGRAM_SET_PEER, 0, &sa.peer); BIO_clear_retry_flags(b); if (ret < 0) @@ -313,14 +402,24 @@ static int dgram_write(BIO *b, const char *in, int inl) bio_dgram_data *data = (bio_dgram_data *)b->ptr; clear_socket_error(); - if ( data->connected ) - ret=writesocket(b->num,in,inl); - else + if ( data->connected ) + ret=writesocket(b->num,in,inl); + else + { + int peerlen = sizeof(data->peer); + + if (data->peer.sa.sa_family == AF_INET) + peerlen = sizeof(data->peer.sa_in); +#if OPENSSL_USE_IPV6 + else if (data->peer.sa.sa_family == AF_INET6) + peerlen = sizeof(data->peer.sa_in6); +#endif #if defined(NETWARE_CLIB) && defined(NETWARE_BSDSOCK) - ret=sendto(b->num, (char *)in, inl, 0, &data->peer, sizeof(data->peer)); + ret=sendto(b->num, (char *)in, inl, 0, &data->peer.sa, peerlen); #else - ret=sendto(b->num, in, inl, 0, &data->peer, sizeof(data->peer)); + ret=sendto(b->num, in, inl, 0, &data->peer.sa, peerlen); #endif + } BIO_clear_retry_flags(b); if (ret <= 0) @@ -352,7 +451,13 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) #endif #ifdef OPENSSL_SYS_LINUX socklen_t addr_len; - struct sockaddr_storage addr; + union { + struct sockaddr sa; + struct sockaddr_in s4; +#if OPENSSL_USE_IPV6 + struct sockaddr_in6 s6; +#endif + } addr; #endif data = (bio_dgram_data *)b->ptr; @@ -406,7 +511,20 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) else { #endif - memcpy(&(data->peer),to, sizeof(struct sockaddr)); + switch (to->sa_family) + { + case AF_INET: + memcpy(&data->peer,to,sizeof(data->peer.sa_in)); + break; +#if OPENSSL_USE_IPV6 + case AF_INET6: + memcpy(&data->peer,to,sizeof(data->peer.sa_in6)); + break; +#endif + default: + memcpy(&data->peer,to,sizeof(data->peer.sa)); + break; + } #if 0 } #endif @@ -414,15 +532,15 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) /* (Linux)kernel sets DF bit on outgoing IP packets */ case BIO_CTRL_DGRAM_MTU_DISCOVER: #ifdef OPENSSL_SYS_LINUX - addr_len = (socklen_t)sizeof(struct sockaddr_storage); - memset((void *)&addr, 0, sizeof(struct sockaddr_storage)); - if (getsockname(b->num, (void *)&addr, &addr_len) < 0) + addr_len = (socklen_t)sizeof(addr); + memset((void *)&addr, 0, sizeof(addr)); + if (getsockname(b->num, &addr.sa, &addr_len) < 0) { ret = 0; break; } sockopt_len = sizeof(sockopt_val); - switch (addr.ss_family) + switch (addr.sa.sa_family) { case AF_INET: sockopt_val = IP_PMTUDISC_DO; @@ -430,12 +548,14 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) &sockopt_val, sizeof(sockopt_val))) < 0) perror("setsockopt"); break; +#if OPENSSL_USE_IPV6 && defined(IPV6_MTU_DISCOVER) case AF_INET6: sockopt_val = IPV6_PMTUDISC_DO; if ((ret = setsockopt(b->num, IPPROTO_IPV6, IPV6_MTU_DISCOVER, &sockopt_val, sizeof(sockopt_val))) < 0) perror("setsockopt"); break; +#endif default: ret = -1; break; @@ -446,15 +566,15 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) #endif case BIO_CTRL_DGRAM_QUERY_MTU: #ifdef OPENSSL_SYS_LINUX - addr_len = (socklen_t)sizeof(struct sockaddr_storage); - memset((void *)&addr, 0, sizeof(struct sockaddr_storage)); - if (getsockname(b->num, (void *)&addr, &addr_len) < 0) + addr_len = (socklen_t)sizeof(addr); + memset((void *)&addr, 0, sizeof(addr)); + if (getsockname(b->num, &addr.sa, &addr_len) < 0) { ret = 0; break; } sockopt_len = sizeof(sockopt_val); - switch (addr.ss_family) + switch (addr.sa.sa_family) { case AF_INET: if ((ret = getsockopt(b->num, IPPROTO_IP, IP_MTU, (void *)&sockopt_val, @@ -471,6 +591,7 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) ret = data->mtu; } break; +#if OPENSSL_USE_IPV6 && defined(IPV6_MTU) case AF_INET6: if ((ret = getsockopt(b->num, IPPROTO_IPV6, IPV6_MTU, (void *)&sockopt_val, &sockopt_len)) < 0 || sockopt_val < 0) @@ -486,6 +607,7 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) ret = data->mtu; } break; +#endif default: ret = 0; break; @@ -495,7 +617,25 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) #endif break; case BIO_CTRL_DGRAM_GET_FALLBACK_MTU: - ret = 576 - 20 - 8; + switch (data->peer.sa.sa_family) + { + case AF_INET: + ret = 576 - 20 - 8; + break; +#if OPENSSL_USE_IPV6 + case AF_INET6: +#ifdef IN6_IS_ADDR_V4MAPPED + if (IN6_IS_ADDR_V4MAPPED(&data->peer.sa_in6.sin6_addr)) + ret = 576 - 20 - 8; + else +#endif + ret = 1280 - 40 - 8; + break; +#endif + default: + ret = 576 - 20 - 8; + break; + } break; case BIO_CTRL_DGRAM_GET_MTU: return data->mtu; @@ -510,27 +650,65 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) if ( to != NULL) { data->connected = 1; - memcpy(&(data->peer),to, sizeof(struct sockaddr)); + switch (to->sa_family) + { + case AF_INET: + memcpy(&data->peer,to,sizeof(data->peer.sa_in)); + break; +#if OPENSSL_USE_IPV6 + case AF_INET6: + memcpy(&data->peer,to,sizeof(data->peer.sa_in6)); + break; +#endif + default: + memcpy(&data->peer,to,sizeof(data->peer.sa)); + break; + } } else { data->connected = 0; - memset(&(data->peer), 0x00, sizeof(struct sockaddr)); + memset(&(data->peer), 0x00, sizeof(data->peer)); + } + break; + case BIO_CTRL_DGRAM_GET_PEER: + switch (data->peer.sa.sa_family) + { + case AF_INET: + ret=sizeof(data->peer.sa_in); + break; +#if OPENSSL_USE_IPV6 + case AF_INET6: + ret=sizeof(data->peer.sa_in6); + break; +#endif + default: + ret=sizeof(data->peer.sa); + break; + } + if (num==0 || num>ret) + num=ret; + memcpy(ptr,&data->peer,(ret=num)); + break; + case BIO_CTRL_DGRAM_SET_PEER: + to = (struct sockaddr *) ptr; + switch (to->sa_family) + { + case AF_INET: + memcpy(&data->peer,to,sizeof(data->peer.sa_in)); + break; +#if OPENSSL_USE_IPV6 + case AF_INET6: + memcpy(&data->peer,to,sizeof(data->peer.sa_in6)); + break; +#endif + default: + memcpy(&data->peer,to,sizeof(data->peer.sa)); + break; } break; - case BIO_CTRL_DGRAM_GET_PEER: - to = (struct sockaddr *) ptr; - - memcpy(to, &(data->peer), sizeof(struct sockaddr)); - ret = sizeof(struct sockaddr); - break; - case BIO_CTRL_DGRAM_SET_PEER: - to = (struct sockaddr *) ptr; - - memcpy(&(data->peer), to, sizeof(struct sockaddr)); - break; case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT: - memcpy(&(data->next_timeout), ptr, sizeof(struct timeval)); + memcpy(&(data->next_timeout), ptr, sizeof(struct timeval)); break; #if defined(SO_RCVTIMEO) case BIO_CTRL_DGRAM_SET_RECV_TIMEOUT: @@ -650,6 +828,912 @@ static int dgram_puts(BIO *bp, const char *str) return(ret); } +#ifndef OPENSSL_NO_SCTP +BIO_METHOD *BIO_s_datagram_sctp(void) + { + return(&methods_dgramp_sctp); + } + +BIO *BIO_new_dgram_sctp(int fd, int close_flag) + { + BIO *bio; + int ret, optval = 20000; + int auth_data = 0, auth_forward = 0; + unsigned char *p; + struct sctp_authchunk auth; + struct sctp_authchunks *authchunks; + socklen_t sockopt_len; +#ifdef SCTP_AUTHENTICATION_EVENT +#ifdef SCTP_EVENT + struct sctp_event event; +#else + struct sctp_event_subscribe event; +#endif +#endif + + bio=BIO_new(BIO_s_datagram_sctp()); + if (bio == NULL) return(NULL); + BIO_set_fd(bio,fd,close_flag); + + /* Activate SCTP-AUTH for DATA and FORWARD-TSN chunks */ + auth.sauth_chunk = OPENSSL_SCTP_DATA_CHUNK_TYPE; + ret = setsockopt(fd, IPPROTO_SCTP, SCTP_AUTH_CHUNK, &auth, sizeof(struct sctp_authchunk)); + OPENSSL_assert(ret >= 0); + auth.sauth_chunk = OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE; + ret = setsockopt(fd, IPPROTO_SCTP, SCTP_AUTH_CHUNK, &auth, sizeof(struct sctp_authchunk)); + OPENSSL_assert(ret >= 0); + + /* Test if activation was successful. When using accept(), + * SCTP-AUTH has to be activated for the listening socket + * already, otherwise the connected socket won't use it. */ + sockopt_len = (socklen_t)(sizeof(sctp_assoc_t) + 256 * sizeof(uint8_t)); + authchunks = OPENSSL_malloc(sockopt_len); + memset(authchunks, 0, sizeof(sockopt_len)); + ret = getsockopt(fd, IPPROTO_SCTP, SCTP_LOCAL_AUTH_CHUNKS, authchunks, &sockopt_len); + OPENSSL_assert(ret >= 0); + + for (p = (unsigned char*) authchunks + sizeof(sctp_assoc_t); + p < (unsigned char*) authchunks + sockopt_len; + p += sizeof(uint8_t)) + { + if (*p == OPENSSL_SCTP_DATA_CHUNK_TYPE) auth_data = 1; + if (*p == OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE) auth_forward = 1; + } + + OPENSSL_free(authchunks); + + OPENSSL_assert(auth_data); + OPENSSL_assert(auth_forward); + +#ifdef SCTP_AUTHENTICATION_EVENT +#ifdef SCTP_EVENT + memset(&event, 0, sizeof(struct sctp_event)); + event.se_assoc_id = 0; + event.se_type = SCTP_AUTHENTICATION_EVENT; + event.se_on = 1; + ret = setsockopt(fd, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(struct sctp_event)); + OPENSSL_assert(ret >= 0); +#else + sockopt_len = (socklen_t) sizeof(struct sctp_event_subscribe); + ret = getsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, &event, &sockopt_len); + OPENSSL_assert(ret >= 0); + + event.sctp_authentication_event = 1; + + ret = setsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct sctp_event_subscribe)); + OPENSSL_assert(ret >= 0); +#endif +#endif + + /* Disable partial delivery by setting the min size + * larger than the max record size of 2^14 + 2048 + 13 + */ + ret = setsockopt(fd, IPPROTO_SCTP, SCTP_PARTIAL_DELIVERY_POINT, &optval, sizeof(optval)); + OPENSSL_assert(ret >= 0); + + return(bio); + } + +int BIO_dgram_is_sctp(BIO *bio) + { + return (BIO_method_type(bio) == BIO_TYPE_DGRAM_SCTP); + } + +static int dgram_sctp_new(BIO *bi) + { + bio_dgram_sctp_data *data = NULL; + + bi->init=0; + bi->num=0; + data = OPENSSL_malloc(sizeof(bio_dgram_sctp_data)); + if (data == NULL) + return 0; + memset(data, 0x00, sizeof(bio_dgram_sctp_data)); +#ifdef SCTP_PR_SCTP_NONE + data->prinfo.pr_policy = SCTP_PR_SCTP_NONE; +#endif + bi->ptr = data; + + bi->flags=0; + return(1); + } + +static int dgram_sctp_free(BIO *a) + { + bio_dgram_sctp_data *data; + + if (a == NULL) return(0); + if ( ! dgram_clear(a)) + return 0; + + data = (bio_dgram_sctp_data *)a->ptr; + if(data != NULL) OPENSSL_free(data); + + return(1); + } + +#ifdef SCTP_AUTHENTICATION_EVENT +void dgram_sctp_handle_auth_free_key_event(BIO *b, union sctp_notification *snp) + { + unsigned int sockopt_len = 0; + int ret; + struct sctp_authkey_event* authkeyevent = &snp->sn_auth_event; + + if (authkeyevent->auth_indication == SCTP_AUTH_FREE_KEY) + { + struct sctp_authkeyid authkeyid; + + /* delete key */ + authkeyid.scact_keynumber = authkeyevent->auth_keynumber; + sockopt_len = sizeof(struct sctp_authkeyid); + ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_DELETE_KEY, + &authkeyid, sockopt_len); + } + } +#endif + +static int dgram_sctp_read(BIO *b, char *out, int outl) + { + int ret = 0, n = 0, i, optval; + socklen_t optlen; + bio_dgram_sctp_data *data = (bio_dgram_sctp_data *)b->ptr; + union sctp_notification *snp; + struct msghdr msg; + struct iovec iov; + struct cmsghdr *cmsg; + char cmsgbuf[512]; + + if (out != NULL) + { + clear_socket_error(); + + do + { + memset(&data->rcvinfo, 0x00, sizeof(struct bio_dgram_sctp_rcvinfo)); + iov.iov_base = out; + iov.iov_len = outl; + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = cmsgbuf; + msg.msg_controllen = 512; + msg.msg_flags = 0; + n = recvmsg(b->num, &msg, 0); + + if (msg.msg_controllen > 0) + { + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) + { + if (cmsg->cmsg_level != IPPROTO_SCTP) + continue; +#ifdef SCTP_RCVINFO + if (cmsg->cmsg_type == SCTP_RCVINFO) + { + struct sctp_rcvinfo *rcvinfo; + + rcvinfo = (struct sctp_rcvinfo *)CMSG_DATA(cmsg); + data->rcvinfo.rcv_sid = rcvinfo->rcv_sid; + data->rcvinfo.rcv_ssn = rcvinfo->rcv_ssn; + data->rcvinfo.rcv_flags = rcvinfo->rcv_flags; + data->rcvinfo.rcv_ppid = rcvinfo->rcv_ppid; + data->rcvinfo.rcv_tsn = rcvinfo->rcv_tsn; + data->rcvinfo.rcv_cumtsn = rcvinfo->rcv_cumtsn; + data->rcvinfo.rcv_context = rcvinfo->rcv_context; + } +#endif +#ifdef SCTP_SNDRCV + if (cmsg->cmsg_type == SCTP_SNDRCV) + { + struct sctp_sndrcvinfo *sndrcvinfo; + + sndrcvinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg); + data->rcvinfo.rcv_sid = sndrcvinfo->sinfo_stream; + data->rcvinfo.rcv_ssn = sndrcvinfo->sinfo_ssn; + data->rcvinfo.rcv_flags = sndrcvinfo->sinfo_flags; + data->rcvinfo.rcv_ppid = sndrcvinfo->sinfo_ppid; + data->rcvinfo.rcv_tsn = sndrcvinfo->sinfo_tsn; + data->rcvinfo.rcv_cumtsn = sndrcvinfo->sinfo_cumtsn; + data->rcvinfo.rcv_context = sndrcvinfo->sinfo_context; + } +#endif + } + } + + if (n <= 0) + { + if (n < 0) + ret = n; + break; + } + + if (msg.msg_flags & MSG_NOTIFICATION) + { + snp = (union sctp_notification*) out; + if (snp->sn_header.sn_type == SCTP_SENDER_DRY_EVENT) + { +#ifdef SCTP_EVENT + struct sctp_event event; +#else + struct sctp_event_subscribe event; + socklen_t eventsize; +#endif + /* If a message has been delayed until the socket + * is dry, it can be sent now. + */ + if (data->saved_message.length > 0) + { + dgram_sctp_write(data->saved_message.bio, data->saved_message.data, + data->saved_message.length); + OPENSSL_free(data->saved_message.data); + data->saved_message.length = 0; + } + + /* disable sender dry event */ +#ifdef SCTP_EVENT + memset(&event, 0, sizeof(struct sctp_event)); + event.se_assoc_id = 0; + event.se_type = SCTP_SENDER_DRY_EVENT; + event.se_on = 0; + i = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(struct sctp_event)); + OPENSSL_assert(i >= 0); +#else + eventsize = sizeof(struct sctp_event_subscribe); + i = getsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, &eventsize); + OPENSSL_assert(i >= 0); + + event.sctp_sender_dry_event = 0; + + i = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct sctp_event_subscribe)); + OPENSSL_assert(i >= 0); +#endif + } + +#ifdef SCTP_AUTHENTICATION_EVENT + if (snp->sn_header.sn_type == SCTP_AUTHENTICATION_EVENT) + dgram_sctp_handle_auth_free_key_event(b, snp); +#endif + + if (data->handle_notifications != NULL) + data->handle_notifications(b, data->notification_context, (void*) out); + + memset(out, 0, outl); + } + else + ret += n; + } + while ((msg.msg_flags & MSG_NOTIFICATION) && (msg.msg_flags & MSG_EOR) && (ret < outl)); + + if (ret > 0 && !(msg.msg_flags & MSG_EOR)) + { + /* Partial message read, this should never happen! */ + + /* The buffer was too small, this means the peer sent + * a message that was larger than allowed. */ + if (ret == outl) + return -1; + + /* Test if socket buffer can handle max record + * size (2^14 + 2048 + 13) + */ + optlen = (socklen_t) sizeof(int); + ret = getsockopt(b->num, SOL_SOCKET, SO_RCVBUF, &optval, &optlen); + OPENSSL_assert(ret >= 0); + OPENSSL_assert(optval >= 18445); + + /* Test if SCTP doesn't partially deliver below + * max record size (2^14 + 2048 + 13) + */ + optlen = (socklen_t) sizeof(int); + ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_PARTIAL_DELIVERY_POINT, + &optval, &optlen); + OPENSSL_assert(ret >= 0); + OPENSSL_assert(optval >= 18445); + + /* Partially delivered notification??? Probably a bug.... */ + OPENSSL_assert(!(msg.msg_flags & MSG_NOTIFICATION)); + + /* Everything seems ok till now, so it's most likely + * a message dropped by PR-SCTP. + */ + memset(out, 0, outl); + BIO_set_retry_read(b); + return -1; + } + + BIO_clear_retry_flags(b); + if (ret < 0) + { + if (BIO_dgram_should_retry(ret)) + { + BIO_set_retry_read(b); + data->_errno = get_last_socket_error(); + } + } + + /* Test if peer uses SCTP-AUTH before continuing */ + if (!data->peer_auth_tested) + { + int ii, auth_data = 0, auth_forward = 0; + unsigned char *p; + struct sctp_authchunks *authchunks; + + optlen = (socklen_t)(sizeof(sctp_assoc_t) + 256 * sizeof(uint8_t)); + authchunks = OPENSSL_malloc(optlen); + memset(authchunks, 0, sizeof(optlen)); + ii = getsockopt(b->num, IPPROTO_SCTP, SCTP_PEER_AUTH_CHUNKS, authchunks, &optlen); + OPENSSL_assert(ii >= 0); + + for (p = (unsigned char*) authchunks + sizeof(sctp_assoc_t); + p < (unsigned char*) authchunks + optlen; + p += sizeof(uint8_t)) + { + if (*p == OPENSSL_SCTP_DATA_CHUNK_TYPE) auth_data = 1; + if (*p == OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE) auth_forward = 1; + } + + OPENSSL_free(authchunks); + + if (!auth_data || !auth_forward) + { + BIOerr(BIO_F_DGRAM_SCTP_READ,BIO_R_CONNECT_ERROR); + return -1; + } + + data->peer_auth_tested = 1; + } + } + return(ret); + } + +static int dgram_sctp_write(BIO *b, const char *in, int inl) + { + int ret; + bio_dgram_sctp_data *data = (bio_dgram_sctp_data *)b->ptr; + struct bio_dgram_sctp_sndinfo *sinfo = &(data->sndinfo); + struct bio_dgram_sctp_prinfo *pinfo = &(data->prinfo); + struct bio_dgram_sctp_sndinfo handshake_sinfo; + struct iovec iov[1]; + struct msghdr msg; + struct cmsghdr *cmsg; +#if defined(SCTP_SNDINFO) && defined(SCTP_PRINFO) + char cmsgbuf[CMSG_SPACE(sizeof(struct sctp_sndinfo)) + CMSG_SPACE(sizeof(struct sctp_prinfo))]; + struct sctp_sndinfo *sndinfo; + struct sctp_prinfo *prinfo; +#else + char cmsgbuf[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))]; + struct sctp_sndrcvinfo *sndrcvinfo; +#endif + + clear_socket_error(); + + /* If we're send anything else than application data, + * disable all user parameters and flags. + */ + if (in[0] != 23) { + memset(&handshake_sinfo, 0x00, sizeof(struct bio_dgram_sctp_sndinfo)); +#ifdef SCTP_SACK_IMMEDIATELY + handshake_sinfo.snd_flags = SCTP_SACK_IMMEDIATELY; +#endif + sinfo = &handshake_sinfo; + } + + /* If we have to send a shutdown alert message and the + * socket is not dry yet, we have to save it and send it + * as soon as the socket gets dry. + */ + if (data->save_shutdown && !BIO_dgram_sctp_wait_for_dry(b)) + { + data->saved_message.bio = b; + data->saved_message.length = inl; + data->saved_message.data = OPENSSL_malloc(inl); + memcpy(data->saved_message.data, in, inl); + return inl; + } + + iov[0].iov_base = (char *)in; + iov[0].iov_len = inl; + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = iov; + msg.msg_iovlen = 1; + msg.msg_control = (caddr_t)cmsgbuf; + msg.msg_controllen = 0; + msg.msg_flags = 0; +#if defined(SCTP_SNDINFO) && defined(SCTP_PRINFO) + cmsg = (struct cmsghdr *)cmsgbuf; + cmsg->cmsg_level = IPPROTO_SCTP; + cmsg->cmsg_type = SCTP_SNDINFO; + cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndinfo)); + sndinfo = (struct sctp_sndinfo *)CMSG_DATA(cmsg); + memset(sndinfo, 0, sizeof(struct sctp_sndinfo)); + sndinfo->snd_sid = sinfo->snd_sid; + sndinfo->snd_flags = sinfo->snd_flags; + sndinfo->snd_ppid = sinfo->snd_ppid; + sndinfo->snd_context = sinfo->snd_context; + msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_sndinfo)); + + cmsg = (struct cmsghdr *)&cmsgbuf[CMSG_SPACE(sizeof(struct sctp_sndinfo))]; + cmsg->cmsg_level = IPPROTO_SCTP; + cmsg->cmsg_type = SCTP_PRINFO; + cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_prinfo)); + prinfo = (struct sctp_prinfo *)CMSG_DATA(cmsg); + memset(prinfo, 0, sizeof(struct sctp_prinfo)); + prinfo->pr_policy = pinfo->pr_policy; + prinfo->pr_value = pinfo->pr_value; + msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_prinfo)); +#else + cmsg = (struct cmsghdr *)cmsgbuf; + cmsg->cmsg_level = IPPROTO_SCTP; + cmsg->cmsg_type = SCTP_SNDRCV; + cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo)); + sndrcvinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg); + memset(sndrcvinfo, 0, sizeof(struct sctp_sndrcvinfo)); + sndrcvinfo->sinfo_stream = sinfo->snd_sid; + sndrcvinfo->sinfo_flags = sinfo->snd_flags; +#ifdef __FreeBSD__ + sndrcvinfo->sinfo_flags |= pinfo->pr_policy; +#endif + sndrcvinfo->sinfo_ppid = sinfo->snd_ppid; + sndrcvinfo->sinfo_context = sinfo->snd_context; + sndrcvinfo->sinfo_timetolive = pinfo->pr_value; + msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_sndrcvinfo)); +#endif + + ret = sendmsg(b->num, &msg, 0); + + BIO_clear_retry_flags(b); + if (ret <= 0) + { + if (BIO_dgram_should_retry(ret)) + { + BIO_set_retry_write(b); + data->_errno = get_last_socket_error(); + } + } + return(ret); + } + +static long dgram_sctp_ctrl(BIO *b, int cmd, long num, void *ptr) + { + long ret=1; + bio_dgram_sctp_data *data = NULL; + unsigned int sockopt_len = 0; + struct sctp_authkeyid authkeyid; + struct sctp_authkey *authkey; + + data = (bio_dgram_sctp_data *)b->ptr; + + switch (cmd) + { + case BIO_CTRL_DGRAM_QUERY_MTU: + /* Set to maximum (2^14) + * and ignore user input to enable transport + * protocol fragmentation. + * Returns always 2^14. + */ + data->mtu = 16384; + ret = data->mtu; + break; + case BIO_CTRL_DGRAM_SET_MTU: + /* Set to maximum (2^14) + * and ignore input to enable transport + * protocol fragmentation. + * Returns always 2^14. + */ + data->mtu = 16384; + ret = data->mtu; + break; + case BIO_CTRL_DGRAM_SET_CONNECTED: + case BIO_CTRL_DGRAM_CONNECT: + /* Returns always -1. */ + ret = -1; + break; + case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT: + /* SCTP doesn't need the DTLS timer + * Returns always 1. + */ + break; + case BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE: + if (num > 0) + data->in_handshake = 1; + else + data->in_handshake = 0; + + ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_NODELAY, &data->in_handshake, sizeof(int)); + break; + case BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY: + /* New shared key for SCTP AUTH. + * Returns 0 on success, -1 otherwise. + */ + + /* Get active key */ + sockopt_len = sizeof(struct sctp_authkeyid); + ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY, &authkeyid, &sockopt_len); + if (ret < 0) break; + + /* Add new key */ + sockopt_len = sizeof(struct sctp_authkey) + 64 * sizeof(uint8_t); + authkey = OPENSSL_malloc(sockopt_len); + memset(authkey, 0x00, sockopt_len); + authkey->sca_keynumber = authkeyid.scact_keynumber + 1; +#ifndef __FreeBSD__ + /* This field is missing in FreeBSD 8.2 and earlier, + * and FreeBSD 8.3 and higher work without it. + */ + authkey->sca_keylength = 64; +#endif + memcpy(&authkey->sca_key[0], ptr, 64 * sizeof(uint8_t)); + + ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_KEY, authkey, sockopt_len); + if (ret < 0) break; + + /* Reset active key */ + ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY, + &authkeyid, sizeof(struct sctp_authkeyid)); + if (ret < 0) break; + + break; + case BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY: + /* Returns 0 on success, -1 otherwise. */ + + /* Get active key */ + sockopt_len = sizeof(struct sctp_authkeyid); + ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY, &authkeyid, &sockopt_len); + if (ret < 0) break; + + /* Set active key */ + authkeyid.scact_keynumber = authkeyid.scact_keynumber + 1; + ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY, + &authkeyid, sizeof(struct sctp_authkeyid)); + if (ret < 0) break; + + /* CCS has been sent, so remember that and fall through + * to check if we need to deactivate an old key + */ + data->ccs_sent = 1; + + case BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD: + /* Returns 0 on success, -1 otherwise. */ + + /* Has this command really been called or is this just a fall-through? */ + if (cmd == BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD) + data->ccs_rcvd = 1; + + /* CSS has been both, received and sent, so deactivate an old key */ + if (data->ccs_rcvd == 1 && data->ccs_sent == 1) + { + /* Get active key */ + sockopt_len = sizeof(struct sctp_authkeyid); + ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_ACTIVE_KEY, &authkeyid, &sockopt_len); + if (ret < 0) break; + + /* Deactivate key or delete second last key if + * SCTP_AUTHENTICATION_EVENT is not available. + */ + authkeyid.scact_keynumber = authkeyid.scact_keynumber - 1; +#ifdef SCTP_AUTH_DEACTIVATE_KEY + sockopt_len = sizeof(struct sctp_authkeyid); + ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_DEACTIVATE_KEY, + &authkeyid, sockopt_len); + if (ret < 0) break; +#endif +#ifndef SCTP_AUTHENTICATION_EVENT + if (authkeyid.scact_keynumber > 0) + { + authkeyid.scact_keynumber = authkeyid.scact_keynumber - 1; + ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_AUTH_DELETE_KEY, + &authkeyid, sizeof(struct sctp_authkeyid)); + if (ret < 0) break; + } +#endif + + data->ccs_rcvd = 0; + data->ccs_sent = 0; + } + break; + case BIO_CTRL_DGRAM_SCTP_GET_SNDINFO: + /* Returns the size of the copied struct. */ + if (num > (long) sizeof(struct bio_dgram_sctp_sndinfo)) + num = sizeof(struct bio_dgram_sctp_sndinfo); + + memcpy(ptr, &(data->sndinfo), num); + ret = num; + break; + case BIO_CTRL_DGRAM_SCTP_SET_SNDINFO: + /* Returns the size of the copied struct. */ + if (num > (long) sizeof(struct bio_dgram_sctp_sndinfo)) + num = sizeof(struct bio_dgram_sctp_sndinfo); + + memcpy(&(data->sndinfo), ptr, num); + break; + case BIO_CTRL_DGRAM_SCTP_GET_RCVINFO: + /* Returns the size of the copied struct. */ + if (num > (long) sizeof(struct bio_dgram_sctp_rcvinfo)) + num = sizeof(struct bio_dgram_sctp_rcvinfo); + + memcpy(ptr, &data->rcvinfo, num); + + ret = num; + break; + case BIO_CTRL_DGRAM_SCTP_SET_RCVINFO: + /* Returns the size of the copied struct. */ + if (num > (long) sizeof(struct bio_dgram_sctp_rcvinfo)) + num = sizeof(struct bio_dgram_sctp_rcvinfo); + + memcpy(&(data->rcvinfo), ptr, num); + break; + case BIO_CTRL_DGRAM_SCTP_GET_PRINFO: + /* Returns the size of the copied struct. */ + if (num > (long) sizeof(struct bio_dgram_sctp_prinfo)) + num = sizeof(struct bio_dgram_sctp_prinfo); + + memcpy(ptr, &(data->prinfo), num); + ret = num; + break; + case BIO_CTRL_DGRAM_SCTP_SET_PRINFO: + /* Returns the size of the copied struct. */ + if (num > (long) sizeof(struct bio_dgram_sctp_prinfo)) + num = sizeof(struct bio_dgram_sctp_prinfo); + + memcpy(&(data->prinfo), ptr, num); + break; + case BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN: + /* Returns always 1. */ + if (num > 0) + data->save_shutdown = 1; + else + data->save_shutdown = 0; + break; + + default: + /* Pass to default ctrl function to + * process SCTP unspecific commands + */ + ret=dgram_ctrl(b, cmd, num, ptr); + break; + } + return(ret); + } + +int BIO_dgram_sctp_notification_cb(BIO *b, + void (*handle_notifications)(BIO *bio, void *context, void *buf), + void *context) + { + bio_dgram_sctp_data *data = (bio_dgram_sctp_data *) b->ptr; + + if (handle_notifications != NULL) + { + data->handle_notifications = handle_notifications; + data->notification_context = context; + } + else + return -1; + + return 0; + } + +int BIO_dgram_sctp_wait_for_dry(BIO *b) +{ + int is_dry = 0; + int n, sockflags, ret; + union sctp_notification snp; + struct msghdr msg; + struct iovec iov; +#ifdef SCTP_EVENT + struct sctp_event event; +#else + struct sctp_event_subscribe event; + socklen_t eventsize; +#endif + bio_dgram_sctp_data *data = (bio_dgram_sctp_data *)b->ptr; + + /* set sender dry event */ +#ifdef SCTP_EVENT + memset(&event, 0, sizeof(struct sctp_event)); + event.se_assoc_id = 0; + event.se_type = SCTP_SENDER_DRY_EVENT; + event.se_on = 1; + ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(struct sctp_event)); +#else + eventsize = sizeof(struct sctp_event_subscribe); + ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, &eventsize); + if (ret < 0) + return -1; + + event.sctp_sender_dry_event = 1; + + ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct sctp_event_subscribe)); +#endif + if (ret < 0) + return -1; + + /* peek for notification */ + memset(&snp, 0x00, sizeof(union sctp_notification)); + iov.iov_base = (char *)&snp; + iov.iov_len = sizeof(union sctp_notification); + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = 0; + + n = recvmsg(b->num, &msg, MSG_PEEK); + if (n <= 0) + { + if ((n < 0) && (get_last_socket_error() != EAGAIN) && (get_last_socket_error() != EWOULDBLOCK)) + return -1; + else + return 0; + } + + /* if we find a notification, process it and try again if necessary */ + while (msg.msg_flags & MSG_NOTIFICATION) + { + memset(&snp, 0x00, sizeof(union sctp_notification)); + iov.iov_base = (char *)&snp; + iov.iov_len = sizeof(union sctp_notification); + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = 0; + + n = recvmsg(b->num, &msg, 0); + if (n <= 0) + { + if ((n < 0) && (get_last_socket_error() != EAGAIN) && (get_last_socket_error() != EWOULDBLOCK)) + return -1; + else + return is_dry; + } + + if (snp.sn_header.sn_type == SCTP_SENDER_DRY_EVENT) + { + is_dry = 1; + + /* disable sender dry event */ +#ifdef SCTP_EVENT + memset(&event, 0, sizeof(struct sctp_event)); + event.se_assoc_id = 0; + event.se_type = SCTP_SENDER_DRY_EVENT; + event.se_on = 0; + ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(struct sctp_event)); +#else + eventsize = (socklen_t) sizeof(struct sctp_event_subscribe); + ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, &eventsize); + if (ret < 0) + return -1; + + event.sctp_sender_dry_event = 0; + + ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct sctp_event_subscribe)); +#endif + if (ret < 0) + return -1; + } + +#ifdef SCTP_AUTHENTICATION_EVENT + if (snp.sn_header.sn_type == SCTP_AUTHENTICATION_EVENT) + dgram_sctp_handle_auth_free_key_event(b, &snp); +#endif + + if (data->handle_notifications != NULL) + data->handle_notifications(b, data->notification_context, (void*) &snp); + + /* found notification, peek again */ + memset(&snp, 0x00, sizeof(union sctp_notification)); + iov.iov_base = (char *)&snp; + iov.iov_len = sizeof(union sctp_notification); + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = 0; + + /* if we have seen the dry already, don't wait */ + if (is_dry) + { + sockflags = fcntl(b->num, F_GETFL, 0); + fcntl(b->num, F_SETFL, O_NONBLOCK); + } + + n = recvmsg(b->num, &msg, MSG_PEEK); + + if (is_dry) + { + fcntl(b->num, F_SETFL, sockflags); + } + + if (n <= 0) + { + if ((n < 0) && (get_last_socket_error() != EAGAIN) && (get_last_socket_error() != EWOULDBLOCK)) + return -1; + else + return is_dry; + } + } + + /* read anything else */ + return is_dry; +} + +int BIO_dgram_sctp_msg_waiting(BIO *b) + { + int n, sockflags; + union sctp_notification snp; + struct msghdr msg; + struct iovec iov; + bio_dgram_sctp_data *data = (bio_dgram_sctp_data *)b->ptr; + + /* Check if there are any messages waiting to be read */ + do + { + memset(&snp, 0x00, sizeof(union sctp_notification)); + iov.iov_base = (char *)&snp; + iov.iov_len = sizeof(union sctp_notification); + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = 0; + + sockflags = fcntl(b->num, F_GETFL, 0); + fcntl(b->num, F_SETFL, O_NONBLOCK); + n = recvmsg(b->num, &msg, MSG_PEEK); + fcntl(b->num, F_SETFL, sockflags); + + /* if notification, process and try again */ + if (n > 0 && (msg.msg_flags & MSG_NOTIFICATION)) + { +#ifdef SCTP_AUTHENTICATION_EVENT + if (snp.sn_header.sn_type == SCTP_AUTHENTICATION_EVENT) + dgram_sctp_handle_auth_free_key_event(b, &snp); +#endif + + memset(&snp, 0x00, sizeof(union sctp_notification)); + iov.iov_base = (char *)&snp; + iov.iov_len = sizeof(union sctp_notification); + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = 0; + n = recvmsg(b->num, &msg, 0); + + if (data->handle_notifications != NULL) + data->handle_notifications(b, data->notification_context, (void*) &snp); + } + + } while (n > 0 && (msg.msg_flags & MSG_NOTIFICATION)); + + /* Return 1 if there is a message to be read, return 0 otherwise. */ + if (n > 0) + return 1; + else + return 0; + } + +static int dgram_sctp_puts(BIO *bp, const char *str) + { + int n,ret; + + n=strlen(str); + ret=dgram_sctp_write(bp,str,n); + return(ret); + } +#endif + static int BIO_dgram_should_retry(int i) { int err; diff --git a/crypto/openssl/crypto/bio/bss_fd.c b/crypto/openssl/crypto/bio/bss_fd.c index 4c229bf..d1bf85a 100644 --- a/crypto/openssl/crypto/bio/bss_fd.c +++ b/crypto/openssl/crypto/bio/bss_fd.c @@ -60,6 +60,13 @@ #include <errno.h> #define USE_SOCKETS #include "cryptlib.h" + +#if defined(OPENSSL_NO_POSIX_IO) +/* + * One can argue that one should implement dummy placeholder for + * BIO_s_fd here... + */ +#else /* * As for unconditional usage of "UPLINK" interface in this module. * Trouble is that unlike Unix file descriptors [which are indexes @@ -77,6 +84,7 @@ 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); @@ -88,7 +96,7 @@ static BIO_METHOD methods_fdp= fd_write, fd_read, fd_puts, - NULL, /* fd_gets, */ + fd_gets, fd_ctrl, fd_new, fd_free, @@ -227,6 +235,22 @@ static int fd_puts(BIO *bp, const char *str) return(ret); } +static int fd_gets(BIO *bp, char *buf, int size) + { + int ret=0; + char *ptr=buf; + char *end=buf+size-1; + + while ( (ptr < end) && (fd_read(bp, ptr, 1) > 0) && (ptr[0] != '\n') ) + ptr++; + + ptr[0]='\0'; + + if (buf[0] != '\0') + ret=strlen(buf); + return(ret); + } + int BIO_fd_should_retry(int i) { int err; @@ -292,3 +316,4 @@ int BIO_fd_non_fatal_error(int err) } return(0); } +#endif diff --git a/crypto/openssl/crypto/bio/bss_file.c b/crypto/openssl/crypto/bio/bss_file.c index 47fa266..b954fe7 100644 --- a/crypto/openssl/crypto/bio/bss_file.c +++ b/crypto/openssl/crypto/bio/bss_file.c @@ -118,10 +118,53 @@ static BIO_METHOD methods_filep= BIO *BIO_new_file(const char *filename, const char *mode) { - BIO *ret; - FILE *file; + BIO *ret; + FILE *file=NULL; + +#if defined(_WIN32) && defined(CP_UTF8) + int sz, len_0 = (int)strlen(filename)+1; + DWORD flags; - if ((file=fopen(filename,mode)) == NULL) + /* + * Basically there are three cases to cover: a) filename is + * pure ASCII string; b) actual UTF-8 encoded string and + * c) locale-ized string, i.e. one containing 8-bit + * characters that are meaningful in current system locale. + * If filename is pure ASCII or real UTF-8 encoded string, + * MultiByteToWideChar succeeds and _wfopen works. If + * filename is locale-ized string, chances are that + * MultiByteToWideChar fails reporting + * ERROR_NO_UNICODE_TRANSLATION, in which case we fall + * back to fopen... + */ + if ((sz=MultiByteToWideChar(CP_UTF8,(flags=MB_ERR_INVALID_CHARS), + filename,len_0,NULL,0))>0 || + (GetLastError()==ERROR_INVALID_FLAGS && + (sz=MultiByteToWideChar(CP_UTF8,(flags=0), + filename,len_0,NULL,0))>0) + ) + { + WCHAR wmode[8]; + WCHAR *wfilename = _alloca(sz*sizeof(WCHAR)); + + if (MultiByteToWideChar(CP_UTF8,flags, + filename,len_0,wfilename,sz) && + MultiByteToWideChar(CP_UTF8,0,mode,strlen(mode)+1, + wmode,sizeof(wmode)/sizeof(wmode[0])) && + (file=_wfopen(wfilename,wmode))==NULL && + (errno==ENOENT || errno==EBADF) + ) /* UTF-8 decode succeeded, but no file, filename + * could still have been locale-ized... */ + file = fopen(filename,mode); + } + else if (GetLastError()==ERROR_NO_UNICODE_TRANSLATION) + { + file = fopen(filename,mode); + } +#else + file=fopen(filename,mode); +#endif + if (file == NULL) { SYSerr(SYS_F_FOPEN,get_last_sys_error()); ERR_add_error_data(5,"fopen('",filename,"','",mode,"')"); @@ -131,7 +174,7 @@ BIO *BIO_new_file(const char *filename, const char *mode) BIOerr(BIO_F_BIO_NEW_FILE,ERR_R_SYS_LIB); return(NULL); } - if ((ret=BIO_new(BIO_s_file_internal())) == NULL) + if ((ret=BIO_new(BIO_s_file())) == NULL) { fclose(file); return(NULL); @@ -286,8 +329,7 @@ static long MS_CALLBACK file_ctrl(BIO *b, int cmd, long num, void *ptr) _setmode(fd,_O_BINARY); #elif defined(OPENSSL_SYS_NETWARE) && defined(NETWARE_CLIB) int fd = fileno((FILE*)ptr); - /* Under CLib there are differences in file modes - */ + /* Under CLib there are differences in file modes */ if (num & BIO_FP_TEXT) setmode(fd,O_TEXT); else @@ -308,7 +350,7 @@ static long MS_CALLBACK file_ctrl(BIO *b, int cmd, long num, void *ptr) else _setmode(fd,_O_BINARY); } -#elif defined(OPENSSL_SYS_OS2) +#elif defined(OPENSSL_SYS_OS2) || defined(OPENSSL_SYS_WIN32_CYGWIN) int fd = fileno((FILE*)ptr); if (num & BIO_FP_TEXT) setmode(fd, O_TEXT); diff --git a/crypto/openssl/crypto/bio/bss_log.c b/crypto/openssl/crypto/bio/bss_log.c index 6360dbc..b7dce5c 100644 --- a/crypto/openssl/crypto/bio/bss_log.c +++ b/crypto/openssl/crypto/bio/bss_log.c @@ -70,12 +70,20 @@ #if defined(OPENSSL_SYS_WINCE) #elif defined(OPENSSL_SYS_WIN32) -# include <process.h> #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(__ultrix) # include <sys/syslog.h> #elif defined(OPENSSL_SYS_NETWARE) @@ -122,18 +130,6 @@ static int MS_CALLBACK 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); -#ifdef OPENSSL_SYS_WIN32 -LONG (WINAPI *go_for_advapi)() = RegOpenKeyEx; -HANDLE (WINAPI *register_event_source)() = NULL; -BOOL (WINAPI *deregister_event_source)() = NULL; -BOOL (WINAPI *report_event)() = NULL; -#define DL_PROC(m,f) (GetProcAddress( m, f )) -#ifdef UNICODE -#define DL_PROC_X(m,f) DL_PROC( m, f "W" ) -#else -#define DL_PROC_X(m,f) DL_PROC( m, f "A" ) -#endif -#endif static BIO_METHOD methods_slg= { @@ -175,7 +171,7 @@ static int MS_CALLBACK slg_write(BIO *b, const char *in, int inl) char* buf; char* pp; int priority, i; - static struct + static const struct { int strl; char str[10]; @@ -249,35 +245,20 @@ static int MS_CALLBACK slg_puts(BIO *bp, const char *str) static void xopenlog(BIO* bp, char* name, int level) { - if ( !register_event_source ) - { - HANDLE advapi; - if ( !(advapi = GetModuleHandle("advapi32")) ) - return; - register_event_source = (HANDLE (WINAPI *)())DL_PROC_X(advapi, - "RegisterEventSource" ); - deregister_event_source = (BOOL (WINAPI *)())DL_PROC(advapi, - "DeregisterEventSource"); - report_event = (BOOL (WINAPI *)())DL_PROC_X(advapi, - "ReportEvent" ); - if ( !(register_event_source && deregister_event_source && - report_event) ) - { - register_event_source = NULL; - deregister_event_source = NULL; - report_event = NULL; - return; - } - } - bp->ptr= (char *)register_event_source(NULL, name); + if (GetVersion() < 0x80000000) + 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; - int pid = _getpid(); - char pidbuf[DECIMAL_SIZE(pid)+4]; + char pidbuf[DECIMAL_SIZE(DWORD)+4]; + + if (bp->ptr == NULL) + return; switch (priority) { @@ -301,19 +282,18 @@ static void xsyslog(BIO *bp, int priority, const char *string) break; } - sprintf(pidbuf, "[%d] ", pid); + sprintf(pidbuf, "[%u] ", GetCurrentProcessId()); lpszStrings[0] = pidbuf; lpszStrings[1] = string; - if(report_event && bp->ptr) - report_event(bp->ptr, evtype, 0, 1024, NULL, 2, 0, + ReportEventA(bp->ptr, evtype, 0, 1024, NULL, 2, 0, lpszStrings, NULL); } static void xcloselog(BIO* bp) { - if(deregister_event_source && bp->ptr) - deregister_event_source((HANDLE)(bp->ptr)); + if(bp->ptr) + DeregisterEventSource((HANDLE)(bp->ptr)); bp->ptr= NULL; } @@ -329,7 +309,24 @@ static void xopenlog(BIO* bp, char* name, int 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; @@ -355,8 +352,8 @@ static void xsyslog(BIO *bp, int priority, const char *string) lib$sys_fao(&fao_cmd, &len, &buf_dsc, priority_tag, string); - /* we know there's an 8 byte header. That's documented */ - opcdef_p = (struct opcdef *) OPENSSL_malloc(8 + len); + /* 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; @@ -364,7 +361,7 @@ static void xsyslog(BIO *bp, int priority, const char *string) opc_dsc.dsc$b_dtype = DSC$K_DTYPE_T; opc_dsc.dsc$b_class = DSC$K_CLASS_S; - opc_dsc.dsc$a_pointer = (char *)opcdef_p; + opc_dsc.dsc$a_pointer = (OPCDEF_TYPE) opcdef_p; opc_dsc.dsc$w_length = len + 8; sys$sndopr(opc_dsc, 0); diff --git a/crypto/openssl/crypto/bio/bss_mem.c b/crypto/openssl/crypto/bio/bss_mem.c index e7ab9cb..37d4194 100644 --- a/crypto/openssl/crypto/bio/bss_mem.c +++ b/crypto/openssl/crypto/bio/bss_mem.c @@ -94,16 +94,18 @@ BIO *BIO_new_mem_buf(void *buf, int len) { BIO *ret; BUF_MEM *b; + size_t sz; + if (!buf) { BIOerr(BIO_F_BIO_NEW_MEM_BUF,BIO_R_NULL_PARAMETER); return NULL; } - if(len == -1) len = strlen(buf); + sz = (len<0) ? strlen(buf) : (size_t)len; if(!(ret = BIO_new(BIO_s_mem())) ) return NULL; b = (BUF_MEM *)ret->ptr; b->data = buf; - b->length = len; - b->max = len; + b->length = sz; + b->max = sz; ret->flags |= BIO_FLAGS_MEM_RDONLY; /* Since this is static data retrying wont help */ ret->num = 0; @@ -144,22 +146,16 @@ static int mem_read(BIO *b, char *out, int outl) { int ret= -1; BUF_MEM *bm; - int i; - char *from,*to; bm=(BUF_MEM *)b->ptr; BIO_clear_retry_flags(b); - ret=(outl > bm->length)?bm->length:outl; + 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; - /* memmove(&(bm->data[0]),&(bm->data[ret]), bm->length); */ if(b->flags & BIO_FLAGS_MEM_RDONLY) bm->data += ret; else { - from=(char *)&(bm->data[ret]); - to=(char *)&(bm->data[0]); - for (i=0; i<bm->length; i++) - to[i]=from[i]; + memmove(&(bm->data[0]),&(bm->data[ret]),bm->length); } } else if (bm->length == 0) { |