Hello community, here is the log from the commit of package openvpn for openSUSE:Factory checked in at 2017-05-08 19:02:41 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/openvpn (Old) and /work/SRC/openSUSE:Factory/.openvpn.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "openvpn" Mon May 8 19:02:41 2017 rev:74 rq:492826 version:2.3.14 Changes: -------- --- /work/SRC/openSUSE:Factory/openvpn/openvpn.changes 2017-01-25 23:33:51.207649062 +0100 +++ /work/SRC/openSUSE:Factory/.openvpn.new/openvpn.changes 2017-05-08 19:03:00.964127085 +0200 @@ -1,0 +2,13 @@ +Fri Apr 21 14:55:09 CEST 2017 - [email protected] + +- Preform deferred authentication in the background to not + cause main daemon processing delays when the underlying pam mechanism (e.g. + ldap) needs longer to response (bsc#959511). + [+ 0001-preform-deferred-authentication-in-the-background.patch] +- Added fix for possible heap overflow on read accessing getaddrinfo + result (bsc#959714). + [+openvpn-2.3.9-Fix-heap-overflow-on-getaddrinfo-result.patch] +- Added a patch to fix multiple low severity issues (bsc#934237). + [+openvpn-2.3.x-fixed-multiple-low-severity-issues.patch] + +------------------------------------------------------------------- New: ---- 0001-preform-deferred-authentication-in-the-background.patch openvpn-2.3.9-Fix-heap-overflow-on-getaddrinfo-result.patch openvpn-2.3.x-fixed-multiple-low-severity-issues.patch ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ openvpn.spec ++++++ --- /var/tmp/diff_new_pack.56XWf9/_old 2017-05-08 19:03:01.879997703 +0200 +++ /var/tmp/diff_new_pack.56XWf9/_new 2017-05-08 19:03:01.883997138 +0200 @@ -51,6 +51,9 @@ Source11: rc%{name} Patch1: %{name}-2.3-plugin-man.dif Patch6: %{name}-fips140-2.3.2.patch +Patch7: openvpn-2.3.9-Fix-heap-overflow-on-getaddrinfo-result.patch +Patch8: openvpn-2.3.x-fixed-multiple-low-severity-issues.patch +Patch9: 0001-preform-deferred-authentication-in-the-background.patch BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildRequires: iproute2 BuildRequires: lzo-devel @@ -135,6 +138,9 @@ %setup -q -n %{name}-%{version} %patch1 -p0 %patch6 -p1 +%patch7 -p1 +%patch8 -p1 +%patch9 -p1 sed -e "s|\" __DATE__|$(date '+%b %e %Y' -r version.m4)\"|g" \ -i src/openvpn/options.c ++++++ 0001-preform-deferred-authentication-in-the-background.patch ++++++ >From 8c39dbd45d3551e838310732a73e05f6d2d2e784 Mon Sep 17 00:00:00 2001 From: Nirmoy Das <[email protected]> Date: Thu, 12 May 2016 12:08:56 +0200 Subject: [PATCH] preform deferred authentication in the background to not cause main daemon processing delays when the underlying pam mechanism (e.g. ldap) needs longer to response. References: bsc#959511 diff --git a/src/plugins/auth-pam/auth-pam.c b/src/plugins/auth-pam/auth-pam.c index bd71792..119fc31 100644 --- a/src/plugins/auth-pam/auth-pam.c +++ b/src/plugins/auth-pam/auth-pam.c @@ -55,6 +55,7 @@ /* Command codes for foreground -> background communication */ #define COMMAND_VERIFY 0 #define COMMAND_EXIT 1 +#define COMMAND_VERIFY_V2 2 /* Response codes for background -> foreground communication */ #define RESPONSE_INIT_SUCCEEDED 10 @@ -108,6 +109,7 @@ struct user_pass { char username[128]; char password[128]; char common_name[128]; + char auth_control_file[PATH_MAX]; const struct name_value_list *name_value_list; }; @@ -687,6 +689,21 @@ pam_auth (const char *service, const struct user_pass *up) return ret; } +static int handle_auth_control_file(char *auth_control_file, int status) +{ + FILE *fp = fopen(auth_control_file, "w"); + + if (fp) { + if (fprintf (fp, "%d\n", status) < 0) { + fclose(fp); + return -1; + } + fclose(fp); + return 0; + } + return -1; +} + /* * Background process -- runs with privilege. */ @@ -781,6 +798,41 @@ pam_server (int fd, const char *service, int verb, const struct name_value_list } break; + case COMMAND_VERIFY_V2: + if (recv_string (fd, up.username, sizeof (up.username)) == -1 + || recv_string (fd, up.password, sizeof (up.password)) == -1 + || recv_string (fd, up.common_name, sizeof (up.common_name)) == -1 + || recv_string (fd, up.auth_control_file, sizeof (up.auth_control_file)) == -1) + { + fprintf (stderr, "AUTH-PAM: BACKGROUND: read error on command channel: code=%d, exiting\n", + command); + goto done; + } + + if (DEBUG (verb)) + { +#if 0 + fprintf (stderr, "AUTH-PAM: BACKGROUND: USER/PASS: %s/%s\n", + up.username, up.password); +#else + fprintf (stderr, "AUTH-PAM: BACKGROUND: USER: %s\n", up.username); +#endif + } + + if (pam_auth (service, &up)) /* Succeeded */ + { + if (handle_auth_control_file(up.auth_control_file, 1) == -1) { + fprintf (stderr, "AUTH-PAM: BACKGROUND: write error on control file\n"); + } + } + else /* Failed */ + { + if (handle_auth_control_file(up.auth_control_file, 0) == -1) { + fprintf (stderr, "AUTH-PAM: BACKGROUND: write error on control file\n"); + } + } + break; + case COMMAND_EXIT: goto done; @@ -804,3 +856,56 @@ pam_server (int fd, const char *service, int verb, const struct name_value_list return; } + +int +handle_auth_pass_verify_v2(struct auth_pam_context *context, const char *argv[], const char *envp[]) +{ + + /* get username/password from envp string array */ + const char *username = get_env ("username", envp); + const char *password = get_env ("password", envp); + const char *common_name = get_env ("common_name", envp) ? get_env ("common_name", envp) : ""; + const char *auth_control_file = get_env ("auth_control_file", envp); + + if (!username || !*username || !password) + return OPENVPN_PLUGIN_FUNC_ERROR; + + if (!auth_control_file || !*auth_control_file || access( auth_control_file, F_OK ) == -1) + return OPENVPN_PLUGIN_FUNC_ERROR; + + if (send_control (context->foreground_fd, COMMAND_VERIFY_V2) == -1 + || send_string (context->foreground_fd, username) == -1 + || send_string (context->foreground_fd, password) == -1 + || send_string (context->foreground_fd, common_name) == -1 + || send_string (context->foreground_fd, auth_control_file) == -1) + { + fprintf (stderr, "AUTH-PAM: Error sending auth info to background process\n"); + } + else + { + return OPENVPN_PLUGIN_FUNC_DEFERRED; + } + + return OPENVPN_PLUGIN_FUNC_ERROR; +} + +OPENVPN_EXPORT int +openvpn_plugin_func_v2 (openvpn_plugin_handle_t handle, + const int type, + const char *argv[], + const char *envp[], + void *per_client_context, + struct openvpn_plugin_string_list **return_list) +{ + struct auth_pam_context *context = (struct auth_pam_context *) handle; + + switch (type) + { + case OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY: + printf ("OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY\n"); + return handle_auth_pass_verify_v2 (context, argv, envp); + default: + printf ("OPENVPN_PLUGIN_?\n"); + return OPENVPN_PLUGIN_FUNC_ERROR; + } +} diff --git a/src/plugins/auth-pam/auth-pam.exports b/src/plugins/auth-pam/auth-pam.exports index b07937c..11a80f1 100644 --- a/src/plugins/auth-pam/auth-pam.exports +++ b/src/plugins/auth-pam/auth-pam.exports @@ -1,4 +1,5 @@ openvpn_plugin_open_v1 openvpn_plugin_func_v1 +openvpn_plugin_func_v2 openvpn_plugin_close_v1 openvpn_plugin_abort_v1 -- 2.6.2 ++++++ openvpn-2.3.9-Fix-heap-overflow-on-getaddrinfo-result.patch ++++++ Author: Gert Doering <[email protected]> Date: Tue Nov 10 22:58:39 2015 +0100 Fix possible heap overflow on read accessing getaddrinfo() result. The code always tried to copy-out a "struct sockaddr_in6" even for IPv4 results, which reads more bytes than getaddrinfo() is guaranteed to allocate. Now, look at ai->ai_family and only copy "struct sockaddr" for IPv4. Also, reformat this block of code to comply to coding style. This is a specific 2.3 bug as the code in master (to be 2.4) has been completely rewritten to properly handle dual-stack and multiple responses from getaddrinfo() proper. Bug found by Daniel Hirche using "gcc -fsanitize=address". No possible exploits are known. Signed-off-by: Gert Doering <[email protected]> Acked-by: Arne Schwabe <[email protected]> Message-Id: <[email protected]> URL: http://article.gmane.org/gmane.network.openvpn.devel/10479 References: bsc#959714 diff --git a/src/openvpn/socket.c b/src/openvpn/socket.c index a143853..0f46bad 100644 --- a/src/openvpn/socket.c +++ b/src/openvpn/socket.c <at> <at> -1259,20 +1259,24 <at> <at> resolve_remote (struct link_socket *sock, ASSERT (0); } - /* Temporary fix, this need to be changed for dual stack */ - status = openvpn_getaddrinfo(flags, sock->remote_host, retry, - signal_received, af, &ai); - if(status == 0) { - sock->info.lsa->remote.addr.in6 = *((struct sockaddr_in6*)(ai->ai_addr)); - freeaddrinfo(ai); + /* Temporary fix, this need to be changed for dual stack */ + status = openvpn_getaddrinfo(flags, sock->remote_host, retry, + signal_received, af, &ai); + if(status == 0) + { + if ( ai->ai_family == AF_INET6 ) + sock->info.lsa->remote.addr.in6 = *((struct sockaddr_in6*)(ai->ai_addr)); + else + sock->info.lsa->remote.addr.in4 = *((struct sockaddr_in*)(ai->ai_addr)); + freeaddrinfo(ai); - dmsg (D_SOCKET_DEBUG, "RESOLVE_REMOTE flags=0x%04x phase=%d rrs=%d sig=%d status=%d", + dmsg (D_SOCKET_DEBUG, "RESOLVE_REMOTE flags=0x%04x phase=%d rrs=%d sig=%d status=%d", flags, phase, retry, signal_received ? *signal_received : -1, status); - } + } if (signal_received) { if (*signal_received) -- 2.4.9 ++++++ openvpn-2.3.x-fixed-multiple-low-severity-issues.patch ++++++ diff --git a/src/openvpn/crypto.c b/src/openvpn/crypto.c index 4261795..44c1f9e 100644 --- a/src/openvpn/crypto.c +++ b/src/openvpn/crypto.c @@ -151,7 +151,7 @@ openvpn_encrypt (struct buffer *buf, struct buffer work, ASSERT (cipher_ctx_reset(ctx->cipher, iv_buf)); /* Buffer overflow check */ - if (!buf_safe (&work, buf->len + cipher_ctx_block_size(ctx->cipher))) + if (!buf_safe (&work, buf->len + OPENVPN_MAX_BLOCK_LENGTH)) { msg (D_CRYPT_ERRORS, "ENCRYPT: buffer size error, bc=%d bo=%d bl=%d wc=%d wo=%d wl=%d cbs=%d", buf->capacity, @@ -278,7 +278,7 @@ openvpn_decrypt (struct buffer *buf, struct buffer work, const int iv_size = cipher_ctx_iv_length (ctx->cipher); const cipher_kt_t *cipher_kt = cipher_ctx_get_cipher_kt (ctx->cipher); uint8_t iv_buf[OPENVPN_MAX_IV_LENGTH]; - int outlen; + int outlen = 0; /* initialize work buffer with FRAME_HEADROOM bytes of prepend capacity */ ASSERT (buf_init (&work, FRAME_HEADROOM_ADJ (frame, FRAME_HEADROOM_MARKER_DECRYPT))); @@ -305,7 +305,7 @@ openvpn_decrypt (struct buffer *buf, struct buffer work, CRYPT_ERROR ("cipher init failed"); /* Buffer overflow check (should never happen) */ - if (!buf_safe (&work, buf->len + cipher_ctx_block_size(ctx->cipher))) + if (!buf_safe (&work, buf->len + OPENVPN_MAX_BLOCK_LENGTH)) CRYPT_ERROR ("potential buffer overflow"); /* Decrypt packet ID, payload */ diff --git a/src/openvpn/crypto_openssl.h b/src/openvpn/crypto_openssl.h index 2ed0bef..ae9f24d 100644 --- a/src/openvpn/crypto_openssl.h +++ b/src/openvpn/crypto_openssl.h @@ -53,6 +53,9 @@ typedef HMAC_CTX hmac_ctx_t; /** Maximum length of an IV */ #define OPENVPN_MAX_IV_LENGTH EVP_MAX_IV_LENGTH +/** Maximum length of a cipher block */ +#define OPENVPN_MAX_BLOCK_LENGTH EVP_MAX_BLOCK_LENGTH + /** Cipher is in CBC mode */ #define OPENVPN_MODE_CBC EVP_CIPH_CBC_MODE diff --git a/src/openvpn/init.c b/src/openvpn/init.c index 089e3c4..e03a3e6 100644 --- a/src/openvpn/init.c +++ b/src/openvpn/init.c @@ -2614,8 +2614,8 @@ init_context_buffers (const struct frame *frame) b->aux_buf = alloc_buf (BUF_SIZE (frame)); #ifdef ENABLE_CRYPTO - b->encrypt_buf = alloc_buf (BUF_SIZE (frame)); - b->decrypt_buf = alloc_buf (BUF_SIZE (frame)); + b->encrypt_buf = alloc_buf (BUF_SIZE (frame) + OPENVPN_MAX_BLOCK_LENGTH); + b->decrypt_buf = alloc_buf (BUF_SIZE (frame) + OPENVPN_MAX_BLOCK_LENGTH); #endif #ifdef ENABLE_LZO diff --git a/src/openvpn/proxy.c b/src/openvpn/proxy.c index 89989d1..5809daa 100644 --- a/src/openvpn/proxy.c +++ b/src/openvpn/proxy.c @@ -76,6 +76,9 @@ recv_line (socket_descriptor_t sd, struct buffer la; int lastc = 0; + if (sd >= FD_SETSIZE) + return false; + CLEAR (la); if (lookahead) la = *lookahead; @@ -283,11 +286,11 @@ get_proxy_authenticate (socket_descriptor_t sd, struct gc_arena *gc, volatile int *signal_received) { - char buf[256]; + char buf[256] = {0}; int ret = HTTP_AUTH_NONE; while (true) { - if (!recv_line (sd, buf, sizeof (buf), timeout, true, NULL, signal_received)) + if (!recv_line (sd, buf, sizeof (buf) - 1, timeout, true, NULL, signal_received)) { *data = NULL; return HTTP_AUTH_NONE; @@ -498,9 +501,9 @@ establish_http_proxy_passthru (struct http_proxy_info *p, volatile int *signal_received) { struct gc_arena gc = gc_new (); - char buf[512]; - char buf2[129]; - char get[80]; + char buf[512] = {0}; + char buf2[129] = {0}; + char get[80] = {0}; int status; int nparms; bool ret = false; @@ -586,7 +589,8 @@ establish_http_proxy_passthru (struct http_proxy_info *p, goto error; /* receive reply from proxy */ - if (!recv_line (sd, buf, sizeof(buf), p->options.timeout, true, NULL, signal_received)) + memset(buf, 0, sizeof(buf)); + if (!recv_line (sd, buf, sizeof(buf) - 1 , p->options.timeout, true, NULL, signal_received)) goto error; /* remove trailing CR, LF */ @@ -615,7 +619,8 @@ establish_http_proxy_passthru (struct http_proxy_info *p, while (true) { - if (!recv_line (sd, buf, sizeof(buf), p->options.timeout, true, NULL, signal_received)) + memset(buf, 0, sizeof(buf)); + if (!recv_line (sd, buf, sizeof(buf) - 1, p->options.timeout, true, NULL, signal_received)) goto error; chomp (buf); msg (D_PROXY, "HTTP proxy returned: '%s'", buf); @@ -685,7 +690,8 @@ establish_http_proxy_passthru (struct http_proxy_info *p, goto error; /* receive reply from proxy */ - if (!recv_line (sd, buf, sizeof(buf), p->options.timeout, true, NULL, signal_received)) + memset(buf, 0, sizeof(buf)); + if (!recv_line (sd, buf, sizeof(buf) - 1, p->options.timeout, true, NULL, signal_received)) goto error; /* remove trailing CR, LF */ @@ -795,7 +801,8 @@ establish_http_proxy_passthru (struct http_proxy_info *p, goto error; /* receive reply from proxy */ - if (!recv_line (sd, buf, sizeof(buf), p->options.timeout, true, NULL, signal_received)) + memset(buf, 0, sizeof(buf)); + if (!recv_line (sd, buf, sizeof(buf) - 1, p->options.timeout, true, NULL, signal_received)) goto error; /* remove trailing CR, LF */ diff --git a/src/openvpn/socket.c b/src/openvpn/socket.c index 3474f18..dfd9d6c 100644 --- a/src/openvpn/socket.c +++ b/src/openvpn/socket.c @@ -832,6 +832,9 @@ socket_listen_accept (socket_descriptor_t sd, struct openvpn_sockaddr remote_verify = act->dest; int new_sd = SOCKET_UNDEFINED; + if (sd >= FD_SETSIZE) + return -1; + CLEAR (*act); socket_do_listen (sd, local, do_listen, true); @@ -919,6 +922,9 @@ openvpn_connect (socket_descriptor_t sd, { int status = 0; + if (sd >= FD_SETSIZE) + return -1; + #ifdef CONNECT_NONBLOCK set_nonblock (sd); status = connect (sd, &remote->addr.sa, af_addr_size(remote->addr.sa.sa_family)); diff --git a/src/openvpn/socks.c b/src/openvpn/socks.c index 57dc02a..8954e91 100644 --- a/src/openvpn/socks.c +++ b/src/openvpn/socks.c @@ -97,13 +97,16 @@ socks_username_password_auth (struct socks_proxy_info *p, socket_descriptor_t sd, volatile int *signal_received) { - char to_send[516]; - char buf[2]; + char to_send[516] = {0}; + char buf[2] = {0}; int len = 0; const int timeout_sec = 5; struct user_pass creds; ssize_t size; + if (sd >= FD_SETSIZE) + return false; + creds.defined = 0; if (!get_user_pass (&creds, p->authfile, UP_TYPE_SOCKS, GET_USER_PASS_MANAGEMENT)) { @@ -189,7 +192,7 @@ socks_handshake (struct socks_proxy_info *p, socket_descriptor_t sd, volatile int *signal_received) { - char buf[2]; + char buf[2] = {0}; int len = 0; const int timeout_sec = 5; ssize_t size; @@ -198,6 +201,8 @@ socks_handshake (struct socks_proxy_info *p, char method_sel[3] = { 0x05, 0x01, 0x00 }; if (p->authfile[0]) method_sel[2] = 0x02; /* METHODS = [2 (plain login)] */ + if (sd >= FD_SETSIZE) + return false; size = send (sd, method_sel, sizeof (method_sel), MSG_NOSIGNAL); if (size != sizeof (method_sel)) @@ -302,9 +307,12 @@ recv_socks_reply (socket_descriptor_t sd, char atyp = '\0'; int alen = 0; int len = 0; - char buf[22]; + char buf[22] = {0}; const int timeout_sec = 5; + if (sd >= FD_SETSIZE) + return false; + if (addr != NULL) { addr->addr.in4.sin_family = AF_INET; @@ -381,7 +389,7 @@ recv_socks_reply (socket_descriptor_t sd, } /* store char in buffer */ - if (len < (int)sizeof(buf)) + if (len < (int)sizeof(buf) && len >= 0) buf[len] = c; ++len; } @@ -411,7 +419,7 @@ establish_socks_proxy_passthru (struct socks_proxy_info *p, const int port, /* openvpn server port */ volatile int *signal_received) { - char buf[128]; + char buf[128] = {0}; size_t len; if (!socks_handshake (p, sd, signal_received))
