Skip to content

Commit dd06cb4

Browse files
committed
Improve err handling rsa and add max request body size for rsa dfi
1 parent 0b909e6 commit dd06cb4

5 files changed

Lines changed: 190 additions & 120 deletions

File tree

‎CHANGES.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ limitations under the License.
124124
- Corrected bundle update behavior when updating bundles from different sources.
125125
- Enhanced `libcurl` initialization procedures and made `libcurl` optional.
126126
- HTTP Admin, Remote Service Admin (DFI) and Remote Shell now keep reading until the full request body / command is received.
127+
- RSA DFI now limits the accepted request body size (configurable via `CELIX_RSA_DFI_MAX_REQUEST_BODY_SIZE_IN_MB`, default 10 (MB)).
127128

128129
## Fixes
129130

‎bundles/http_admin/http_admin/src/http_admin.c‎

Lines changed: 52 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@
3131

3232
#include "celix_compiler.h"
3333
#include "celix_threads.h"
34+
#include "celix_stdlib_cleanup.h"
35+
36+
#define CELIX_HTTP_ADMIN_READ_ERROR_MSG "Bad Request: Read error"
37+
#define CELIX_HTTP_ADMIN_INCOMPLETE_BODY_MSG "Bad Request: Incomplete Body"
38+
#define CELIX_HTTP_ADMIN_INSUFFICIENT_MEM_MSG "Server Error: Insufficient memory"
3439

3540

3641
struct http_admin_manager {
@@ -56,7 +61,11 @@ typedef struct http_alias {
5661

5762
//Local function prototypes
5863
static int http_request_handle(struct mg_connection *connection);
59-
static bool httpAdmin_readRequestBody(struct mg_connection *connection, long long content_length, char **bufferOut, size_t *bytesReadOut);
64+
/**
65+
* @brief read the request body.
66+
* @return 0 if succesfull, > 0 and a error code (4xx or 5xx) if not sucessfull.
67+
*/
68+
static int httpAdmin_readRequestBody(struct mg_connection *connection, long long content_length, char **bufferOut, size_t *bytesReadOut, const char** errorMsgOut);
6069
static void httpAdmin_updateInfoSvc(http_admin_manager_t *admin);
6170
static void createAliasesSymlink(const char *aliases, const char *admin_root, const char *bundle_root, long bundle_id, celix_array_list_t *alias_list);
6271
static bool aliasList_containsAlias(celix_array_list_t *alias_list, const char *alias);
@@ -174,32 +183,37 @@ void http_admin_removeHttpService(void *handle, void *svc CELIX_UNUSED, const ce
174183
}
175184
}
176185

177-
static bool httpAdmin_readRequestBody(struct mg_connection* connection, long long contentLength, char** bufferOut, size_t* bytesReadOut) {
178-
char* buffer = NULL;
186+
static int httpAdmin_readRequestBody(struct mg_connection* connection, long long contentLength, char** bufferOut, size_t* bytesReadOut, const char** errorMsgOut) {
187+
celix_autofree char* buffer = NULL;
179188
size_t totalBytesRead = 0;
180-
bool success = true;
189+
*errorMsgOut = NULL;
181190
if (contentLength > 0) {
182191
size_t length = (contentLength > INT_MAX) ? INT_MAX : (size_t)contentLength;
183192
buffer = malloc(length + 1);
184193
if (buffer == NULL) {
185-
success = false;
186-
} else {
187-
while (totalBytesRead < length) {
188-
int read = mg_read(connection, buffer + totalBytesRead, length - totalBytesRead);
189-
if (read <= 0) {
190-
success = false;
191-
break;
192-
}
193-
totalBytesRead += (size_t)read;
194-
}
195-
if (success) {
196-
buffer[totalBytesRead] = '\0';
194+
*errorMsgOut = CELIX_HTTP_ADMIN_INSUFFICIENT_MEM_MSG;
195+
return 500;
196+
}
197+
198+
while (totalBytesRead < length) {
199+
int read = mg_read(connection, buffer + totalBytesRead, length - totalBytesRead);
200+
if (read == 0) {
201+
break; //EOF
202+
} else if (read < 0) {
203+
*errorMsgOut = CELIX_HTTP_ADMIN_READ_ERROR_MSG;
204+
return 400;
197205
}
206+
totalBytesRead += (size_t)read;
207+
}
208+
if (totalBytesRead < length) {
209+
*errorMsgOut = CELIX_HTTP_ADMIN_INCOMPLETE_BODY_MSG;
210+
return 400;
198211
}
212+
buffer[totalBytesRead] = '\0';
199213
}
200-
*bufferOut = buffer;
214+
*bufferOut = celix_steal_ptr(buffer);
201215
*bytesReadOut = totalBytesRead;
202-
return success;
216+
return 0;
203217
}
204218

205219
int http_request_handle(struct mg_connection *connection) {
@@ -239,12 +253,13 @@ int http_request_handle(struct mg_connection *connection) {
239253
if (httpSvc->doPost != NULL) {
240254
char *rcv_buf = NULL;
241255
size_t bytesRead = 0;
242-
bool success = httpAdmin_readRequestBody(connection, ri->content_length, &rcv_buf, &bytesRead);
243-
if (success) {
256+
const char* errMsg;
257+
int errCode = httpAdmin_readRequestBody(connection, ri->content_length, &rcv_buf, &bytesRead, &errMsg);
258+
if (errCode == 0) {
244259
ret_status = httpSvc->doPost(httpSvc->handle, connection, rcv_buf, bytesRead);
245260
} else {
246-
mg_send_http_error(connection, 400, "%s", "Bad request");
247-
ret_status = 400; //Bad Request, failed to read data
261+
mg_send_http_error(connection, errCode, "%s", errMsg);
262+
ret_status = errCode; //set status to the error code, so the request is not passed to civetweb
248263
}
249264
free(rcv_buf);
250265
} else {
@@ -255,12 +270,13 @@ int http_request_handle(struct mg_connection *connection) {
255270
if (httpSvc->doPut != NULL) {
256271
char *rcv_buf = NULL;
257272
size_t bytesRead = 0;
258-
bool success = httpAdmin_readRequestBody(connection, ri->content_length, &rcv_buf, &bytesRead);
259-
if (success) {
273+
const char* errMsg;
274+
int errCode = httpAdmin_readRequestBody(connection, ri->content_length, &rcv_buf, &bytesRead, &errMsg);
275+
if (errCode == 0) {
260276
ret_status = httpSvc->doPut(httpSvc->handle, connection, req_uri, rcv_buf, bytesRead);
261277
} else {
262-
mg_send_http_error(connection, 400, "%s", "Bad request");
263-
ret_status = 400; //Bad Request, failed to read data
278+
mg_send_http_error(connection, errCode, "%s", errMsg);
279+
ret_status = errCode; //set status to the error code, so the request is not passed to civetweb
264280
}
265281
free(rcv_buf);
266282
} else {
@@ -276,12 +292,13 @@ int http_request_handle(struct mg_connection *connection) {
276292
if (httpSvc->doTrace != NULL) {
277293
char *rcv_buf = NULL;
278294
size_t bytesRead = 0;
279-
bool success = httpAdmin_readRequestBody(connection, ri->content_length, &rcv_buf, &bytesRead);
280-
if (success) {
295+
const char* errMsg = NULL;
296+
int errCode = httpAdmin_readRequestBody(connection, ri->content_length, &rcv_buf, &bytesRead, &errMsg);
297+
if (errCode == 0) {
281298
ret_status = httpSvc->doTrace(httpSvc->handle, connection, rcv_buf, bytesRead);
282299
} else {
283-
mg_send_http_error(connection, 400, "%s", "Bad request");
284-
ret_status = 400; //Bad Request, failed to read data
300+
mg_send_http_error(connection, errCode, "%s", errMsg);
301+
ret_status = errCode; //set status to the error code, so the request is not passed to civetweb
285302
}
286303
free(rcv_buf);
287304
} else {
@@ -297,12 +314,13 @@ int http_request_handle(struct mg_connection *connection) {
297314
if (httpSvc->doPatch != NULL) {
298315
char *rcv_buf = NULL;
299316
size_t bytesRead = 0;
300-
bool success = httpAdmin_readRequestBody(connection, ri->content_length, &rcv_buf, &bytesRead);
301-
if (success) {
317+
const char* errMsg;
318+
int errCode = httpAdmin_readRequestBody(connection, ri->content_length, &rcv_buf, &bytesRead, &errMsg);
319+
if (errCode == 0) {
302320
ret_status = httpSvc->doPatch(httpSvc->handle, connection, req_uri, rcv_buf, bytesRead);
303321
} else {
304-
mg_send_http_error(connection, 400, "%s", "Bad request");
305-
ret_status = 400; //Bad Request, failed to read data
322+
mg_send_http_error(connection, errCode, "%s", errMsg);
323+
ret_status = errCode; //set status to the error code, so the request is not passed to civetweb
306324
}
307325
free(rcv_buf);
308326
} else {

‎bundles/remote_services/remote_service_admin_dfi/README.md‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,5 +41,8 @@ Libffi is configured using descriptor files in the bundles.
4141

4242
CELIX_RSA_DFI_DYNAMIC_IP_SUPPORT If set to true the RSA will support dynamic IP address fill-in for service exports. Default is false.
4343

44+
CELIX_RSA_DFI_MAX_REQUEST_BODY_SIZE_IN_MB The maximum size of the accepted request body in megabytes. Requests with a body larger
45+
than this limit are rejected with an HTTP 413 response. Default is 10 MB.
46+
4447
###### CMake option
4548
RSA_REMOTE_SERVICE_ADMIN_DFI=ON

0 commit comments

Comments
 (0)