Skip to content
Snippets Groups Projects
Commit bd0aa4fb authored by Kevin Harwell's avatar Kevin Harwell
Browse files

res_http_websocket: read/write string fixup

There was a problem when reading a string from the websocket. It assumed the
received data had a null terminator and tried to write the data to an ast_str.
This of course could/would read past the end of the given buffer while
writing the data to the internal buffer of ast_str. Modified the the code to
correctly place a null terminator on the result string.


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@416394 65c4cc65-6c06-0410-ace0-fbb531ad65f3
parent a1e0a5e4
No related branches found
No related tags found
No related merge requests found
...@@ -156,6 +156,8 @@ AST_OPTIONAL_API(int, ast_websocket_read, (struct ast_websocket *session, char * ...@@ -156,6 +156,8 @@ AST_OPTIONAL_API(int, ast_websocket_read, (struct ast_websocket *session, char *
/*! /*!
* \brief Read a WebSocket frame containing string data. * \brief Read a WebSocket frame containing string data.
* *
* \note The caller is responsible for freeing the output "buf".
*
* \param ws pointer to the websocket * \param ws pointer to the websocket
* \param buf string buffer to populate with data read from socket * \param buf string buffer to populate with data read from socket
* \retval -1 on error * \retval -1 on error
...@@ -164,7 +166,7 @@ AST_OPTIONAL_API(int, ast_websocket_read, (struct ast_websocket *session, char * ...@@ -164,7 +166,7 @@ AST_OPTIONAL_API(int, ast_websocket_read, (struct ast_websocket *session, char *
* \note Once an AST_WEBSOCKET_OPCODE_CLOSE opcode is received the socket will be closed * \note Once an AST_WEBSOCKET_OPCODE_CLOSE opcode is received the socket will be closed
*/ */
AST_OPTIONAL_API(int, ast_websocket_read_string, AST_OPTIONAL_API(int, ast_websocket_read_string,
(struct ast_websocket *ws, struct ast_str **buf), (struct ast_websocket *ws, char **buf),
{ errno = ENOSYS; return -1;}); { errno = ENOSYS; return -1;});
/*! /*!
...@@ -189,7 +191,7 @@ AST_OPTIONAL_API(int, ast_websocket_write, (struct ast_websocket *session, enum ...@@ -189,7 +191,7 @@ AST_OPTIONAL_API(int, ast_websocket_write, (struct ast_websocket *session, enum
* \retval -1 if error occurred * \retval -1 if error occurred
*/ */
AST_OPTIONAL_API(int, ast_websocket_write_string, AST_OPTIONAL_API(int, ast_websocket_write_string,
(struct ast_websocket *ws, const struct ast_str *buf), (struct ast_websocket *ws, const char *buf),
{ errno = ENOSYS; return -1;}); { errno = ENOSYS; return -1;});
/*! /*!
* \brief Close a WebSocket session by sending a message with the CLOSE opcode and an optional code * \brief Close a WebSocket session by sending a message with the CLOSE opcode and an optional code
......
...@@ -497,7 +497,6 @@ int AST_OPTIONAL_API_NAME(ast_websocket_read)(struct ast_websocket *session, cha ...@@ -497,7 +497,6 @@ int AST_OPTIONAL_API_NAME(ast_websocket_read)(struct ast_websocket *session, cha
if (ws_safe_read(session, (*payload), (*payload_len), opcode)) { if (ws_safe_read(session, (*payload), (*payload_len), opcode)) {
return 0; return 0;
} }
/* If a mask is present unmask the payload */ /* If a mask is present unmask the payload */
if (mask_present) { if (mask_present) {
unsigned int pos; unsigned int pos;
...@@ -1199,19 +1198,13 @@ struct ast_websocket *AST_OPTIONAL_API_NAME(ast_websocket_client_create) ...@@ -1199,19 +1198,13 @@ struct ast_websocket *AST_OPTIONAL_API_NAME(ast_websocket_client_create)
} }
int AST_OPTIONAL_API_NAME(ast_websocket_read_string) int AST_OPTIONAL_API_NAME(ast_websocket_read_string)
(struct ast_websocket *ws, struct ast_str **buf) (struct ast_websocket *ws, char **buf)
{ {
char *payload; char *payload;
uint64_t payload_len; uint64_t payload_len;
enum ast_websocket_opcode opcode; enum ast_websocket_opcode opcode;
int fragmented = 1; int fragmented = 1;
if (!*buf && !(*buf = ast_str_create(512))) {
ast_log(LOG_ERROR, "Client Websocket string read - "
"Unable to allocate string buffer");
return -1;
}
while (fragmented) { while (fragmented) {
if (ast_websocket_read(ws, &payload, &payload_len, if (ast_websocket_read(ws, &payload, &payload_len,
&opcode, &fragmented)) { &opcode, &fragmented)) {
...@@ -1220,6 +1213,10 @@ int AST_OPTIONAL_API_NAME(ast_websocket_read_string) ...@@ -1220,6 +1213,10 @@ int AST_OPTIONAL_API_NAME(ast_websocket_read_string)
return -1; return -1;
} }
if (opcode == AST_WEBSOCKET_OPCODE_CONTINUATION) {
continue;
}
if (opcode == AST_WEBSOCKET_OPCODE_CLOSE) { if (opcode == AST_WEBSOCKET_OPCODE_CLOSE) {
return -1; return -1;
} }
...@@ -1229,17 +1226,21 @@ int AST_OPTIONAL_API_NAME(ast_websocket_read_string) ...@@ -1229,17 +1226,21 @@ int AST_OPTIONAL_API_NAME(ast_websocket_read_string)
"non string data received\n"); "non string data received\n");
return -1; return -1;
} }
}
ast_str_append(buf, 0, "%s", payload); if (!(*buf = ast_malloc(payload_len + 1))) {
return -1;
} }
return ast_str_size(*buf);
ast_copy_string(*buf, payload, payload_len + 1);
return payload_len + 1;
} }
int AST_OPTIONAL_API_NAME(ast_websocket_write_string) int AST_OPTIONAL_API_NAME(ast_websocket_write_string)
(struct ast_websocket *ws, const struct ast_str *buf) (struct ast_websocket *ws, const char *buf)
{ {
return ast_websocket_write(ws, AST_WEBSOCKET_OPCODE_TEXT, return ast_websocket_write(ws, AST_WEBSOCKET_OPCODE_TEXT,
ast_str_buffer(buf), ast_str_strlen(buf)); (char *)buf, strlen(buf));
} }
static int load_module(void) static int load_module(void)
......
...@@ -48,8 +48,8 @@ AST_TEST_DEFINE(websocket_client_create_and_connect) ...@@ -48,8 +48,8 @@ AST_TEST_DEFINE(websocket_client_create_and_connect)
RAII_VAR(struct ast_websocket *, client, NULL, ao2_cleanup); RAII_VAR(struct ast_websocket *, client, NULL, ao2_cleanup);
enum ast_websocket_result result; enum ast_websocket_result result;
struct ast_str *write_buf; const char write_buf[] = "this is only a test";
struct ast_str *read_buf; RAII_VAR(char *, read_buf, NULL, ast_free);
switch (cmd) { switch (cmd) {
case TEST_INIT: case TEST_INIT:
...@@ -62,16 +62,12 @@ AST_TEST_DEFINE(websocket_client_create_and_connect) ...@@ -62,16 +62,12 @@ AST_TEST_DEFINE(websocket_client_create_and_connect)
break; break;
} }
write_buf = ast_str_alloca(20);
read_buf = ast_str_alloca(20);
ast_test_validate(test, (client = ast_websocket_client_create( ast_test_validate(test, (client = ast_websocket_client_create(
REMOTE_URL, "echo", NULL, &result))); REMOTE_URL, "echo", NULL, &result)));
ast_str_set(&write_buf, 0, "this is only a test");
ast_test_validate(test, !ast_websocket_write_string(client, write_buf)); ast_test_validate(test, !ast_websocket_write_string(client, write_buf));
ast_test_validate(test, ast_websocket_read_string(client, &read_buf) > 0); ast_test_validate(test, ast_websocket_read_string(client, &read_buf) > 0);
ast_test_validate(test, !strcmp(ast_str_buffer(write_buf), ast_str_buffer(read_buf))); ast_test_validate(test, !strcmp(write_buf, read_buf));
return AST_TEST_PASS; return AST_TEST_PASS;
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment