diff --git a/src/openvpn/forward.c b/src/openvpn/forward.c index 404b71c8..e8b981b3 100644 --- a/src/openvpn/forward.c +++ b/src/openvpn/forward.c @@ -221,6 +221,46 @@ parse_incoming_control_channel_command(struct context *c, struct buffer *buf) } } +static struct buffer +extract_command_buffer(struct buffer *buf, struct gc_arena *gc) +{ + /* commands on the control channel are seperated by 0x00 bytes. + * cmdlen does not include the 0 byte of the string */ + int cmdlen = (int)strnlen(BSTR(buf), BLEN(buf)); + + if (cmdlen >= BLEN(buf)) + { + buf_advance(buf, cmdlen); + /* Return empty buffer */ + struct buffer empty = { 0 }; + return empty; + } + + /* include the NUL byte and ensure NUL termination */ + cmdlen += 1; + + /* Construct a buffer that only holds the current command and + * its closing NUL byte */ + struct buffer cmdbuf = alloc_buf_gc(cmdlen, gc); + buf_write(&cmdbuf, BPTR(buf), cmdlen); + + /* Remove \r and \n at the end of the buffer to avoid + * problems with scripts and other that add extra \r and \n */ + buf_chomp(&cmdbuf); + + /* check we have only printable characters or null byte in the + * command string and no newlines */ + if (!string_check_buf(&cmdbuf, CC_PRINT | CC_NULL, CC_CRLF)) + { + msg(D_PUSH_ERRORS, "WARNING: Received control with invalid characters: %s", + format_hex(BPTR(&cmdbuf), BLEN(&cmdbuf), 256, gc)); + cmdbuf.len = 0; + } + + buf_advance(buf, cmdlen); + return cmdbuf; +} + /* * Handle incoming configuration * messages on the control channel. @@ -236,41 +276,14 @@ check_incoming_control_channel(struct context *c) struct buffer buf = alloc_buf_gc(len, &gc); if (tls_rec_payload(c->c2.tls_multi, &buf)) { - while (BLEN(&buf) > 1) { - /* commands on the control channel are seperated by 0x00 bytes. - * cmdlen does not include the 0 byte of the string */ - int cmdlen = (int)strnlen(BSTR(&buf), BLEN(&buf)); + struct buffer cmdbuf = extract_command_buffer(&buf, &gc); - if (cmdlen < BLEN(&buf)) + if (cmdbuf.len > 0) { - /* include the NUL byte and ensure NUL termination */ - int cmdlen = (int)strlen(BSTR(&buf)) + 1; - - /* Construct a buffer that only holds the current command and - * its closing NUL byte */ - struct buffer cmdbuf = alloc_buf_gc(cmdlen, &gc); - buf_write(&cmdbuf, BPTR(&buf), cmdlen); - - /* check we have only printable characters or null byte in the - * command string and no newlines */ - if (!string_check_buf(&buf, CC_PRINT | CC_NULL, CC_CRLF)) - { - msg(D_PUSH_ERRORS, "WARNING: Received control with invalid characters: %s", - format_hex(BPTR(&buf), BLEN(&buf), 256, &gc)); - } - else - { - parse_incoming_control_channel_command(c, &cmdbuf); - } + parse_incoming_control_channel_command(c, &cmdbuf); } - else - { - msg(D_PUSH_ERRORS, "WARNING: Ignoring control channel " - "message command without NUL termination"); - } - buf_advance(&buf, cmdlen); } } else