From 67f27ea223a20721ac288508635b5148e6264d56 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Sat, 7 Jan 2023 12:45:01 +0100 Subject: [PATCH] clt: check if rpc command has execution limit with delta interval --- src/modules/ctl/binrpc_run.c | 26 ++++++++++++++++---------- src/modules/ctl/fifo_server.c | 30 +++++++++++++++++++----------- 2 files changed, 35 insertions(+), 21 deletions(-) diff --git a/src/modules/ctl/binrpc_run.c b/src/modules/ctl/binrpc_run.c index 5950ad64002..41c501320d4 100644 --- a/src/modules/ctl/binrpc_run.c +++ b/src/modules/ctl/binrpc_run.c @@ -22,6 +22,7 @@ #include "binrpc.h" #include "../../core/dprint.h" #include "../../core/rpc.h" +#include "../../core/rpc_lookup.h" #include "../../core/sr_module.h" #include "../../core/mem/mem.h" #include "../../core/clist.h" @@ -614,10 +615,10 @@ static int rpc_send(struct binrpc_ctx* ctx) /* params: buf, size - buffer containing the packet * bytes_needed - int pointer, filled with how many bytes are still * needed (after bytes_needed new bytes received this - * function will be called again + * function will be called again * reply, - buffer where the reply will be written * reply_len - intially filled with the reply buffer len, - * after the call will contain how much of that + * after the call will contain how much of that * buffer was really used * returns: number of bytes processed on success/partial success * -1 on error @@ -627,9 +628,10 @@ int process_rpc_req(unsigned char* buf, int size, int* bytes_needed, { int err; struct binrpc_val val; - rpc_export_t* rpc_e; + rpc_exportx_t* rpc_e; struct binrpc_ctx f_ctx; struct binrpc_parse_ctx* ctx; + unsigned int rdata; if(ksr_shutdown_phase()) { /* during shutdown - no more RPC command handling */ @@ -666,7 +668,7 @@ int process_rpc_req(unsigned char* buf, int size, int* bytes_needed, goto error; } /* now we have the entire packet */ - + /* get rpc method */ val.type=BINRPC_T_STR; f_ctx.in.s=binrpc_read_record(ctx, f_ctx.in.s, f_ctx.in.end, &val, 0, &err); @@ -676,16 +678,20 @@ int process_rpc_req(unsigned char* buf, int size, int* bytes_needed, rpc_fault(&f_ctx, 400, "bad request method: %s", binrpc_error(err) ); goto error; } - - /* find_rpc_exports needs 0 terminated strings, but all str are - * 0 term by default */ - rpc_e=find_rpc_export(val.u.strval.s, 0); - if ((rpc_e==0) || (rpc_e->function==0)){ + + rpc_e = rpc_lookupx(val.u.strval.s, val.u.strval.len, &rdata); + if ((rpc_e==NULL) || (rpc_e->r.function==NULL)){ rpc_fault(&f_ctx, 500, "command %s not found", val.u.strval.s); goto end; } + if (rdata & RPC_EXEC_DELTA) { + LM_ERR("execution of command [%.*s] is limited by delta [%d]\n", + val.u.strval.len, val.u.strval.s, ksr_rpc_exec_delta); + rpc_fault(&f_ctx, 500, "Command Executed Too Fast"); + goto end; + } f_ctx.method=val.u.strval.s; - rpc_e->function(&binrpc_callbacks, &f_ctx); + rpc_e->r.function(&binrpc_callbacks, &f_ctx); if (f_ctx.replied==0){ if ((binrpc_pkt_len(&f_ctx.out.pkt)==0) && f_ctx.err_code && f_ctx.err_phrase.s diff --git a/src/modules/ctl/fifo_server.c b/src/modules/ctl/fifo_server.c index 9a0949cfe74..584ec624f49 100644 --- a/src/modules/ctl/fifo_server.c +++ b/src/modules/ctl/fifo_server.c @@ -84,6 +84,7 @@ #include "../../core/sr_module.h" #include "../../core/pt.h" #include "../../core/rpc.h" +#include "../../core/rpc_lookup.h" #include "../../core/tsend.h" #include "fifo_server.h" #include "io_listener.h" @@ -667,7 +668,7 @@ static int open_reply_pipe(char *pipe_name) int fifo_process(char* msg_buf, int size, int* bytes_needed, void *sh, void** saved_state) { - rpc_export_t* exp; + rpc_exportx_t* exp; char* buf; int line_len; char *file_sep; @@ -675,7 +676,8 @@ int fifo_process(char* msg_buf, int size, int* bytes_needed, void *sh, struct rpc_struct* s; int r; int req_size; - static rpc_ctx_t context; + static rpc_ctx_t context; + unsigned int rdata; DBG("process_fifo: called with %d bytes, offset %d: %.*s\n", size, (int)(long)*saved_state, size, msg_buf); @@ -747,7 +749,7 @@ int fifo_process(char* msg_buf, int size, int* bytes_needed, void *sh, ERR("Empty command\n"); goto consume; } - if (*(file_sep + 1) == 0) context.reply_file = NULL; + if (*(file_sep + 1) == 0) context.reply_file = NULL; else { context.reply_file = file_sep + 1; context.reply_file = trim_filename(context.reply_file); @@ -758,26 +760,32 @@ int fifo_process(char* msg_buf, int size, int* bytes_needed, void *sh, } /* make command zero-terminated */ *file_sep = 0; - - exp = find_rpc_export(context.method, 0); - if (!exp || !exp->function) { + + exp = rpc_lookupx(context.method, strlen(context.method), &rdata); + if ((exp==NULL) || (exp->r.function==NULL)){ DBG("Command %s not found\n", context.method); rpc_fault(&context, 500, "Command '%s' not found", context.method); goto consume; } + if (rdata & RPC_EXEC_DELTA) { + LM_ERR("execution of command [%s] is limited by delta [%d]\n", + context.method, ksr_rpc_exec_delta); + rpc_fault(&context, 500, "Command Executed Too Fast"); + goto consume; + } - exp->function(&func_param, &context); + exp->r.function(&func_param, &context); consume: if (!context.reply_sent) { rpc_send(&context); } - if (context.reply_file) { - ctl_free(context.reply_file); - context.reply_file = 0; + if (context.reply_file) { + ctl_free(context.reply_file); + context.reply_file = 0; } - + /* Collect garbage (unescaped strings and structures) */ while(context.strs) { p = context.strs;