X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=crypto%2Fbio%2Fbss_dgram.c;h=0975856d59aa40bb0fc3e1e4744092f4be324828;hb=03dc77e07bf0f60a39872946405f1188daad3604;hp=aef81499aae5de43403df692a8263832ad3e924c;hpb=918bb8652969fd53f0c390c1cd909265ed502c7e;p=oweals%2Fopenssl.git diff --git a/crypto/bio/bss_dgram.c b/crypto/bio/bss_dgram.c index aef81499aa..0975856d59 100644 --- a/crypto/bio/bss_dgram.c +++ b/crypto/bio/bss_dgram.c @@ -60,7 +60,7 @@ #include #include #define USE_SOCKETS -#include "cryptlib.h" +#include "internal/cryptlib.h" #include #ifndef OPENSSL_NO_DGRAM @@ -169,6 +169,7 @@ typedef struct bio_dgram_data_st { unsigned int mtu; struct timeval next_timeout; struct timeval socket_timeout; + unsigned int peekmode; } bio_dgram_data; # ifndef OPENSSL_NO_SCTP @@ -221,17 +222,11 @@ BIO *BIO_new_dgram(int fd, int close_flag) static int dgram_new(BIO *bi) { - bio_dgram_data *data = NULL; + bio_dgram_data *data = OPENSSL_zalloc(sizeof(*data)); - bi->init = 0; - bi->num = 0; - data = OPENSSL_malloc(sizeof(bio_dgram_data)); if (data == NULL) return 0; - memset(data, 0x00, sizeof(bio_dgram_data)); bi->ptr = data; - - bi->flags = 0; return (1); } @@ -245,8 +240,7 @@ static int dgram_free(BIO *a) return 0; data = (bio_dgram_data *)a->ptr; - if (data != NULL) - OPENSSL_free(data); + OPENSSL_free(data); return (1); } @@ -306,16 +300,17 @@ static void dgram_adjust_rcv_timeout(BIO *b) /* Calculate time left until timer expires */ memcpy(&timeleft, &(data->next_timeout), sizeof(struct timeval)); - timeleft.tv_sec -= timenow.tv_sec; - timeleft.tv_usec -= timenow.tv_usec; - if (timeleft.tv_usec < 0) { + if (timeleft.tv_usec < timenow.tv_usec) { + timeleft.tv_usec = 1000000 - timenow.tv_usec + timeleft.tv_usec; timeleft.tv_sec--; - timeleft.tv_usec += 1000000; + } else { + timeleft.tv_usec -= timenow.tv_usec; } - - if (timeleft.tv_sec < 0) { + if (timeleft.tv_sec < timenow.tv_sec) { timeleft.tv_sec = 0; timeleft.tv_usec = 1; + } else { + timeleft.tv_sec -= timenow.tv_sec; } /* @@ -373,6 +368,7 @@ static int dgram_read(BIO *b, char *out, int outl) { int ret = 0; bio_dgram_data *data = (bio_dgram_data *)b->ptr; + int flags = 0; struct { /* @@ -396,9 +392,11 @@ static int dgram_read(BIO *b, char *out, int outl) if (out != NULL) { clear_socket_error(); - memset(&sa.peer, 0x00, sizeof(sa.peer)); + memset(&sa.peer, 0, sizeof(sa.peer)); dgram_adjust_rcv_timeout(b); - ret = recvfrom(b->num, out, outl, 0, &sa.peer.sa, (void *)&sa.len); + if (data->peekmode) + flags = MSG_PEEK; + ret = recvfrom(b->num, out, outl, flags, &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; @@ -514,10 +512,8 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) switch (cmd) { case BIO_CTRL_RESET: num = 0; - case BIO_C_FILE_SEEK: ret = 0; break; - case BIO_C_FILE_TELL: case BIO_CTRL_INFO: ret = 0; break; @@ -570,7 +566,7 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) case BIO_CTRL_DGRAM_MTU_DISCOVER: # if defined(OPENSSL_SYS_LINUX) && defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO) addr_len = (socklen_t) sizeof(addr); - memset((void *)&addr, 0, sizeof(addr)); + memset(&addr, 0, sizeof(addr)); if (getsockname(b->num, &addr.sa, &addr_len) < 0) { ret = 0; break; @@ -601,7 +597,7 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) case BIO_CTRL_DGRAM_QUERY_MTU: # if defined(OPENSSL_SYS_LINUX) && defined(IP_MTU) addr_len = (socklen_t) sizeof(addr); - memset((void *)&addr, 0, sizeof(addr)); + memset(&addr, 0, sizeof(addr)); if (getsockname(b->num, &addr.sa, &addr_len) < 0) { ret = 0; break; @@ -694,7 +690,7 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) } } else { data->connected = 0; - memset(&(data->peer), 0x00, sizeof(data->peer)); + memset(&data->peer, 0, sizeof(data->peer)); } break; case BIO_CTRL_DGRAM_GET_PEER: @@ -882,7 +878,7 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) perror("setsockopt"); ret = -1; } -# elif defined(OPENSSL_SYS_LINUX) && defined(IP_MTUDISCOVER) +# elif defined(OPENSSL_SYS_LINUX) && defined(IP_MTU_DISCOVER) && defined (IP_PMTUDISC_PROBE) if ((sockopt_val = num ? IP_PMTUDISC_PROBE : IP_PMTUDISC_DONT), (ret = setsockopt(b->num, IPPROTO_IP, IP_MTU_DISCOVER, &sockopt_val, sizeof(sockopt_val))) < 0) { @@ -929,6 +925,9 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) case BIO_CTRL_DGRAM_GET_MTU_OVERHEAD: ret = dgram_get_mtu_overhead(data); break; + case BIO_CTRL_DGRAM_SET_PEEK_MODE: + data->peekmode = (unsigned int)num; + break; default: ret = 0; break; @@ -997,16 +996,13 @@ BIO *BIO_new_dgram_sctp(int fd, int close_flag) * connected socket won't use it. */ sockopt_len = (socklen_t) (sizeof(sctp_assoc_t) + 256 * sizeof(uint8_t)); - authchunks = OPENSSL_malloc(sockopt_len); - if(!authchunks) { + authchunks = OPENSSL_zalloc(sockopt_len); + if (authchunks == NULL) { BIO_vfree(bio); return (NULL); } - memset(authchunks, 0, sockopt_len); - ret = - getsockopt(fd, IPPROTO_SCTP, SCTP_LOCAL_AUTH_CHUNKS, authchunks, + ret = getsockopt(fd, IPPROTO_SCTP, SCTP_LOCAL_AUTH_CHUNKS, authchunks, &sockopt_len); - if (ret < 0) { OPENSSL_free(authchunks); BIO_vfree(bio); @@ -1029,7 +1025,7 @@ BIO *BIO_new_dgram_sctp(int fd, int close_flag) # ifdef SCTP_AUTHENTICATION_EVENT # ifdef SCTP_EVENT - memset(&event, 0, sizeof(struct sctp_event)); + memset(&event, 0, sizeof(event)); event.se_assoc_id = 0; event.se_type = SCTP_AUTHENTICATION_EVENT; event.se_on = 1; @@ -1086,10 +1082,9 @@ static int dgram_sctp_new(BIO *bi) bi->init = 0; bi->num = 0; - data = OPENSSL_malloc(sizeof(bio_dgram_sctp_data)); + data = OPENSSL_zalloc(sizeof(*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 @@ -1110,8 +1105,7 @@ static int dgram_sctp_free(BIO *a) data = (bio_dgram_sctp_data *) a->ptr; if (data != NULL) { - if (data->saved_message.data != NULL) - OPENSSL_free(data->saved_message.data); + OPENSSL_free(data->saved_message.data); OPENSSL_free(data); } @@ -1151,8 +1145,7 @@ static int dgram_sctp_read(BIO *b, char *out, int outl) clear_socket_error(); do { - memset(&data->rcvinfo, 0x00, - sizeof(struct bio_dgram_sctp_rcvinfo)); + memset(&data->rcvinfo, 0, sizeof(data->rcvinfo)); iov.iov_base = out; iov.iov_len = outl; msg.msg_name = NULL; @@ -1221,9 +1214,13 @@ static int dgram_sctp_read(BIO *b, char *out, int outl) * it can be sent now. */ if (data->saved_message.length > 0) { - dgram_sctp_write(data->saved_message.bio, + i = dgram_sctp_write(data->saved_message.bio, data->saved_message.data, data->saved_message.length); + if (i < 0) { + ret = i; + break; + } OPENSSL_free(data->saved_message.data); data->saved_message.data = NULL; data->saved_message.length = 0; @@ -1231,7 +1228,7 @@ static int dgram_sctp_read(BIO *b, char *out, int outl) /* disable sender dry event */ # ifdef SCTP_EVENT - memset(&event, 0, sizeof(struct sctp_event)); + memset(&event, 0, sizeof(event)); event.se_assoc_id = 0; event.se_type = SCTP_SENDER_DRY_EVENT; event.se_on = 0; @@ -1337,8 +1334,8 @@ static int dgram_sctp_read(BIO *b, char *out, int outl) optlen = (socklen_t) (sizeof(sctp_assoc_t) + 256 * sizeof(uint8_t)); authchunks = OPENSSL_malloc(optlen); - if (!authchunks) { - BIOerr(BIO_F_DGRAM_SCTP_READ, ERR_R_MALLOC_ERROR); + if (authchunks == NULL) { + BIOerr(BIO_F_DGRAM_SCTP_READ, ERR_R_MALLOC_FAILURE); return -1; } memset(authchunks, 0, optlen); @@ -1368,6 +1365,14 @@ static int dgram_sctp_read(BIO *b, char *out, int outl) return (ret); } +/* + * dgram_sctp_write - send message on SCTP socket + * @b: BIO to write to + * @in: data to send + * @inl: amount of bytes in @in to send + * + * Returns -1 on error or the sent amount of bytes on success + */ static int dgram_sctp_write(BIO *b, const char *in, int inl) { int ret; @@ -1395,7 +1400,7 @@ static int dgram_sctp_write(BIO *b, const char *in, int inl) * parameters and flags. */ if (in[0] != 23) { - memset(&handshake_sinfo, 0x00, sizeof(struct bio_dgram_sctp_sndinfo)); + memset(&handshake_sinfo, 0, sizeof(handshake_sinfo)); # ifdef SCTP_SACK_IMMEDIATELY handshake_sinfo.snd_flags = SCTP_SACK_IMMEDIATELY; # endif @@ -1406,19 +1411,24 @@ static int dgram_sctp_write(BIO *b, const char *in, int inl) * 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)) { - char *tmp; - data->saved_message.bio = b; - if(!(tmp = OPENSSL_malloc(inl))) { - BIOerr(BIO_F_DGRAM_SCTP_WRITE, ERR_R_MALLOC_ERROR); + if (data->save_shutdown) { + ret = BIO_dgram_sctp_wait_for_dry(b); + if (ret < 0) { return -1; } - if (data->saved_message.data) + if (ret == 0) { + char *tmp; + data->saved_message.bio = b; + if ((tmp = OPENSSL_malloc(inl)) == NULL) { + BIOerr(BIO_F_DGRAM_SCTP_WRITE, ERR_R_MALLOC_FAILURE); + return -1; + } OPENSSL_free(data->saved_message.data); - data->saved_message.data = tmp; - memcpy(data->saved_message.data, in, inl); - data->saved_message.length = inl; - return inl; + data->saved_message.data = tmp; + memcpy(data->saved_message.data, in, inl); + data->saved_message.length = inl; + return inl; + } } iov[0].iov_base = (char *)in; @@ -1436,7 +1446,7 @@ static int dgram_sctp_write(BIO *b, const char *in, int inl) 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)); + memset(sndinfo, 0, sizeof(*sndinfo)); sndinfo->snd_sid = sinfo->snd_sid; sndinfo->snd_flags = sinfo->snd_flags; sndinfo->snd_ppid = sinfo->snd_ppid; @@ -1449,7 +1459,7 @@ static int dgram_sctp_write(BIO *b, const char *in, int inl) 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)); + memset(prinfo, 0, sizeof(*prinfo)); prinfo->pr_policy = pinfo->pr_policy; prinfo->pr_value = pinfo->pr_value; msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_prinfo)); @@ -1459,7 +1469,7 @@ static int dgram_sctp_write(BIO *b, const char *in, int inl) 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)); + memset(sndrcvinfo, 0, sizeof(*sndrcvinfo)); sndrcvinfo->sinfo_stream = sinfo->snd_sid; sndrcvinfo->sinfo_flags = sinfo->snd_flags; # ifdef __FreeBSD__ @@ -1556,7 +1566,7 @@ static long dgram_sctp_ctrl(BIO *b, int cmd, long num, void *ptr) ret = -1; break; } - memset(authkey, 0x00, sockopt_len); + memset(authkey, 0, sockopt_len); authkey->sca_keynumber = authkeyid.scact_keynumber + 1; # ifndef __FreeBSD__ /* @@ -1736,6 +1746,19 @@ int BIO_dgram_sctp_notification_cb(BIO *b, return 0; } +/* + * BIO_dgram_sctp_wait_for_dry - Wait for SCTP SENDER_DRY event + * @b: The BIO to check for the dry event + * + * Wait until the peer confirms all packets have been received, and so that + * our kernel doesn't have anything to send anymore. This is only received by + * the peer's kernel, not the application. + * + * Returns: + * -1 on error + * 0 when not dry yet + * 1 when dry + */ int BIO_dgram_sctp_wait_for_dry(BIO *b) { int is_dry = 0; @@ -1753,7 +1776,7 @@ int BIO_dgram_sctp_wait_for_dry(BIO *b) /* set sender dry event */ # ifdef SCTP_EVENT - memset(&event, 0, sizeof(struct sctp_event)); + memset(&event, 0, sizeof(event)); event.se_assoc_id = 0; event.se_type = SCTP_SENDER_DRY_EVENT; event.se_on = 1; @@ -1776,7 +1799,7 @@ int BIO_dgram_sctp_wait_for_dry(BIO *b) return -1; /* peek for notification */ - memset(&snp, 0x00, sizeof(union sctp_notification)); + memset(&snp, 0, sizeof(snp)); iov.iov_base = (char *)&snp; iov.iov_len = sizeof(union sctp_notification); msg.msg_name = NULL; @@ -1798,7 +1821,7 @@ int BIO_dgram_sctp_wait_for_dry(BIO *b) /* 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)); + memset(&snp, 0, sizeof(snp)); iov.iov_base = (char *)&snp; iov.iov_len = sizeof(union sctp_notification); msg.msg_name = NULL; @@ -1823,7 +1846,7 @@ int BIO_dgram_sctp_wait_for_dry(BIO *b) /* disable sender dry event */ # ifdef SCTP_EVENT - memset(&event, 0, sizeof(struct sctp_event)); + memset(&event, 0, sizeof(event)); event.se_assoc_id = 0; event.se_type = SCTP_SENDER_DRY_EVENT; event.se_on = 0; @@ -1857,7 +1880,7 @@ int BIO_dgram_sctp_wait_for_dry(BIO *b) (void *)&snp); /* found notification, peek again */ - memset(&snp, 0x00, sizeof(union sctp_notification)); + memset(&snp, 0, sizeof(snp)); iov.iov_base = (char *)&snp; iov.iov_len = sizeof(union sctp_notification); msg.msg_name = NULL; @@ -1903,7 +1926,7 @@ int BIO_dgram_sctp_msg_waiting(BIO *b) /* Check if there are any messages waiting to be read */ do { - memset(&snp, 0x00, sizeof(union sctp_notification)); + memset(&snp, 0, sizeof(snp)); iov.iov_base = (char *)&snp; iov.iov_len = sizeof(union sctp_notification); msg.msg_name = NULL; @@ -1926,7 +1949,7 @@ int BIO_dgram_sctp_msg_waiting(BIO *b) dgram_sctp_handle_auth_free_key_event(b, &snp); # endif - memset(&snp, 0x00, sizeof(union sctp_notification)); + memset(&snp, 0, sizeof(snp)); iov.iov_base = (char *)&snp; iov.iov_len = sizeof(union sctp_notification); msg.msg_name = NULL;