diff options
-rw-r--r-- | channels/chan_sip.c | 160 | ||||
-rw-r--r-- | channels/chan_skinny.c | 77 | ||||
-rw-r--r-- | channels/sip/include/sip.h | 4 | ||||
-rw-r--r-- | configs/http.conf.sample | 5 | ||||
-rw-r--r-- | configs/sip.conf.sample | 10 | ||||
-rw-r--r-- | configs/skinny.conf.sample | 9 | ||||
-rw-r--r-- | main/http.c | 22 | ||||
-rw-r--r-- | main/manager.c | 37 |
8 files changed, 295 insertions, 29 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c index a608c783e..2938fc879 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -559,6 +559,10 @@ static int max_expiry = DEFAULT_MAX_EXPIRY; /*!< Maximum accepted registr static int default_expiry = DEFAULT_DEFAULT_EXPIRY; static int mwi_expiry = DEFAULT_MWI_EXPIRY; +static int unauth_sessions = 0; +static int authlimit = DEFAULT_AUTHLIMIT; +static int authtimeout = DEFAULT_AUTHTIMEOUT; + /*! \brief Global jitterbuffer configuration - by default, jb is disabled */ static struct ast_jb_conf default_jbconf = { @@ -2456,21 +2460,48 @@ static void *sip_tcp_worker_fn(void *data) return _sip_tcp_helper_thread(NULL, tcptls_session); } +/*! \brief Check if the authtimeout has expired. + * \param start the time when the session started + * + * \retval 0 the timeout has expired + * \retval -1 error + * \return the number of milliseconds until the timeout will expire + */ +static int sip_check_authtimeout(time_t start) +{ + int timeout; + time_t now; + if(time(&now) == -1) { + ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno)); + return -1; + } + + timeout = (authtimeout - (now - start)) * 1000; + if (timeout < 0) { + /* we have timed out */ + return 0; + } + + return timeout; +} + /*! \brief SIP TCP thread management function This function reads from the socket, parses the packet into a request */ static void *_sip_tcp_helper_thread(struct sip_pvt *pvt, struct ast_tcptls_session_instance *tcptls_session) { - int res, cl; + int res, cl, timeout = -1, authenticated = 0, flags; + time_t start; struct sip_request req = { 0, } , reqcpy = { 0, }; struct sip_threadinfo *me = NULL; char buf[1024] = ""; struct pollfd fds[2] = { { 0 }, { 0 }, }; struct ast_tcptls_session_args *ca = NULL; - /* If this is a server session, then the connection has already been setup, - * simply create the threadinfo object so we can access this thread for writing. - * + /* If this is a server session, then the connection has already been + * setup. Check if the authlimit has been reached and if not create the + * threadinfo object so we can access this thread for writing. + * * if this is a client connection more work must be done. * 1. We own the parent session args for a client connection. This pointer needs * to be held on to so we can decrement it's ref count on thread destruction. @@ -2479,6 +2510,22 @@ static void *_sip_tcp_helper_thread(struct sip_pvt *pvt, struct ast_tcptls_sessi * 3. Last, the tcptls_session must be started. */ if (!tcptls_session->client) { + if (ast_atomic_fetchadd_int(&unauth_sessions, +1) >= authlimit) { + /* unauth_sessions is decremented in the cleanup code */ + goto cleanup; + } + + if ((flags = fcntl(tcptls_session->fd, F_GETFL)) == -1) { + ast_log(LOG_ERROR, "error setting socket to non blocking mode, fcntl() failed: %s\n", strerror(errno)); + goto cleanup; + } + + flags |= O_NONBLOCK; + if (fcntl(tcptls_session->fd, F_SETFL, flags) == -1) { + ast_log(LOG_ERROR, "error setting socket to non blocking mode, fcntl() failed: %s\n", strerror(errno)); + goto cleanup; + } + if (!(me = sip_threadinfo_create(tcptls_session, tcptls_session->ssl ? SIP_TRANSPORT_TLS : SIP_TRANSPORT_TCP))) { goto cleanup; } @@ -2510,13 +2557,41 @@ static void *_sip_tcp_helper_thread(struct sip_pvt *pvt, struct ast_tcptls_sessi goto cleanup; } + if(time(&start) == -1) { + ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno)); + goto cleanup; + } + for (;;) { struct ast_str *str_save; - res = ast_poll(fds, 2, -1); /* polls for both socket and alert_pipe */ + if (!tcptls_session->client && req.authenticated && !authenticated) { + authenticated = 1; + ast_atomic_fetchadd_int(&unauth_sessions, -1); + } + + /* calculate the timeout for unauthenticated server sessions */ + if (!tcptls_session->client && !authenticated ) { + if ((timeout = sip_check_authtimeout(start)) < 0) { + goto cleanup; + } + + if (timeout == 0) { + ast_debug(2, "SIP %s server timed out\n", tcptls_session->ssl ? "SSL": "TCP"); + goto cleanup; + } + } else { + timeout = -1; + } + + res = ast_poll(fds, 2, timeout); /* polls for both socket and alert_pipe */ if (res < 0) { ast_debug(2, "SIP %s server :: ast_wait_for_input returned %d\n", tcptls_session->ssl ? "SSL": "TCP", res); goto cleanup; + } else if (res == 0) { + /* timeout */ + ast_debug(2, "SIP %s server timed out\n", tcptls_session->ssl ? "SSL": "TCP"); + goto cleanup; } /* handle the socket event, check for both reads from the socket fd, @@ -2549,6 +2624,29 @@ static void *_sip_tcp_helper_thread(struct sip_pvt *pvt, struct ast_tcptls_sessi /* Read in headers one line at a time */ while (req.len < 4 || strncmp(REQ_OFFSET_TO_STR(&req, len - 4), "\r\n\r\n", 4)) { + if (!tcptls_session->client && !authenticated ) { + if ((timeout = sip_check_authtimeout(start)) < 0) { + goto cleanup; + } + + if (timeout == 0) { + ast_debug(2, "SIP %s server timed out\n", tcptls_session->ssl ? "SSL": "TCP"); + goto cleanup; + } + } else { + timeout = -1; + } + + res = ast_wait_for_input(tcptls_session->fd, timeout); + if (res < 0) { + ast_debug(2, "SIP %s server :: ast_wait_for_input returned %d\n", tcptls_session->ssl ? "SSL": "TCP", res); + goto cleanup; + } else if (res == 0) { + /* timeout */ + ast_debug(2, "SIP %s server timed out\n", tcptls_session->ssl ? "SSL": "TCP"); + goto cleanup; + } + ast_mutex_lock(&tcptls_session->lock); if (!fgets(buf, sizeof(buf), tcptls_session->f)) { ast_mutex_unlock(&tcptls_session->lock); @@ -2567,6 +2665,29 @@ static void *_sip_tcp_helper_thread(struct sip_pvt *pvt, struct ast_tcptls_sessi if (sscanf(get_header(&reqcpy, "Content-Length"), "%30d", &cl)) { while (cl > 0) { size_t bytes_read; + if (!tcptls_session->client && !authenticated ) { + if ((timeout = sip_check_authtimeout(start)) < 0) { + goto cleanup; + } + + if (timeout == 0) { + ast_debug(2, "SIP %s server timed out", tcptls_session->ssl ? "SSL": "TCP"); + goto cleanup; + } + } else { + timeout = -1; + } + + res = ast_wait_for_input(tcptls_session->fd, timeout); + if (res < 0) { + ast_debug(2, "SIP %s server :: ast_wait_for_input returned %d\n", tcptls_session->ssl ? "SSL": "TCP", res); + goto cleanup; + } else if (res == 0) { + /* timeout */ + ast_debug(2, "SIP %s server timed out", tcptls_session->ssl ? "SSL": "TCP"); + goto cleanup; + } + ast_mutex_lock(&tcptls_session->lock); if (!(bytes_read = fread(buf, 1, MIN(sizeof(buf) - 1, cl), tcptls_session->f))) { ast_mutex_unlock(&tcptls_session->lock); @@ -2626,6 +2747,10 @@ static void *_sip_tcp_helper_thread(struct sip_pvt *pvt, struct ast_tcptls_sessi ast_debug(2, "Shutting down thread for %s server\n", tcptls_session->ssl ? "SSL" : "TCP"); cleanup: + if (!tcptls_session->client && !authenticated) { + ast_atomic_fetchadd_int(&unauth_sessions, -1); + } + if (me) { ao2_t_unlink(threadt, me, "Removing tcptls helper thread, thread is closing"); ao2_t_ref(me, -1, "Removing tcp_helper_threads threadinfo ref"); @@ -21789,6 +21914,8 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int } } + req->authenticated = 1; + /* We have a successful authentication, process the SDP portion if there is one */ if (find_sdp(req)) { if (process_sdp(p, req, SDP_T38_INITIATE)) { @@ -24020,8 +24147,10 @@ static int handle_request_register(struct sip_pvt *p, struct sip_request *req, s get_header(req, "To"), ast_sockaddr_stringify(addr), reason); append_history(p, "RegRequest", "Failed : Account %s : %s", get_header(req, "To"), reason); - } else + } else { + req->authenticated = 1; append_history(p, "RegRequest", "Succeeded : Account %s", get_header(req, "To")); + } if (res < 1) { /* Destroy the session, but keep us around for just a bit in case they don't @@ -24407,6 +24536,11 @@ static int handle_request_do(struct sip_request *req, struct ast_sockaddr *addr) copy_socket_data(&p->socket, &req->socket); ast_sockaddr_copy(&p->recv, addr); + /* if we have an owner, then this request has been authenticated */ + if (p->owner) { + req->authenticated = 1; + } + if (p->do_history) /* This is a request or response, note what it was for */ append_history(p, "Rx", "%s / %s / %s", req->data->str, get_header(req, "CSeq"), REQ_OFFSET_TO_STR(req, rlPart2)); @@ -27073,6 +27207,8 @@ static int reload_config(enum channelreloadreason reason) global_qualifyfreq = DEFAULT_QUALIFYFREQ; global_t38_maxdatagram = -1; global_shrinkcallerid = 1; + authlimit = DEFAULT_AUTHLIMIT; + authtimeout = DEFAULT_AUTHTIMEOUT; sip_cfg.matchexternaddrlocally = DEFAULT_MATCHEXTERNADDRLOCALLY; @@ -27336,6 +27472,18 @@ static int reload_config(enum channelreloadreason reason) if (mwi_expiry < 1) { mwi_expiry = DEFAULT_MWI_EXPIRY; } + } else if (!strcasecmp(v->name, "tcpauthtimeout")) { + if (ast_parse_arg(v->value, PARSE_INT32|PARSE_DEFAULT|PARSE_IN_RANGE, + &authtimeout, DEFAULT_AUTHTIMEOUT, 1, INT_MAX)) { + ast_log(LOG_WARNING, "Invalid %s '%s' at line %d of %s\n", + v->name, v->value, v->lineno, config); + } + } else if (!strcasecmp(v->name, "tcpauthlimit")) { + if (ast_parse_arg(v->value, PARSE_INT32|PARSE_DEFAULT|PARSE_IN_RANGE, + &authlimit, DEFAULT_AUTHLIMIT, 1, INT_MAX)) { + ast_log(LOG_WARNING, "Invalid %s '%s' at line %d of %s\n", + v->name, v->value, v->lineno, config); + } } else if (!strcasecmp(v->name, "sipdebug")) { if (ast_true(v->value)) sipdebug |= sip_debug_config; diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c index b93af9f0f..a105b6c21 100644 --- a/channels/chan_skinny.c +++ b/channels/chan_skinny.c @@ -164,6 +164,8 @@ enum skinny_codecs { #define DEFAULT_SKINNY_PORT 2000 #define DEFAULT_SKINNY_BACKLOG 2 #define SKINNY_MAX_PACKET 1000 +#define DEFAULT_AUTH_TIMEOUT 30 +#define DEFAULT_AUTH_LIMIT 50 static struct { unsigned int tos; @@ -175,6 +177,9 @@ static struct { } qos = { 0, 0, 0, 0, 0, 0 }; static int keep_alive = 120; +static int auth_timeout = DEFAULT_AUTH_TIMEOUT; +static int auth_limit = DEFAULT_AUTH_LIMIT; +static int unauth_sessions = 0; static char global_vmexten[AST_MAX_EXTENSION]; /* Voicemail pilot number */ static char used_context[AST_MAX_EXTENSION]; /* placeholder to check if context are already used in regcontext */ static char regcontext[AST_MAX_CONTEXT]; /* Context for auto-extension */ @@ -1374,6 +1379,7 @@ static struct ast_jb_conf global_jbconf;*/ struct skinnysession { pthread_t t; ast_mutex_t lock; + time_t start; struct sockaddr_in sin; int fd; char inbuf[SKINNY_MAX_PACKET]; @@ -6119,6 +6125,7 @@ static int handle_message(struct skinny_req *req, struct skinnysession *s) break; case REGISTER_MESSAGE: if (skinny_register(req, s)) { + ast_atomic_fetchadd_int(&unauth_sessions, -1); ast_verb(3, "Device '%s' successfully registered\n", s->device->name); transmit_registerack(s->device); transmit_capabilitiesreq(s->device); @@ -6286,6 +6293,9 @@ static void destroy_session(struct skinnysession *s) if (s->fd > -1) close(s->fd); + if (!s->device) + ast_atomic_fetchadd_int(&unauth_sessions, -1); + ast_mutex_destroy(&s->lock); ast_free(s); @@ -6301,13 +6311,30 @@ static int get_input(struct skinnysession *s) { int res; int dlen = 0; + int timeout = keep_alive * 1100; + time_t now; int *bufaddr; struct pollfd fds[1]; + if (!s->device) { + if(time(&now) == -1) { + ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno)); + return -1; + } + + timeout = (auth_timeout - (now - s->start)) * 1000; + if (timeout < 0) { + /* we have timed out */ + if (skinnydebug) + ast_verb(1, "Skinny Client failed to authenticate in %d seconds\n", auth_timeout); + return -1; + } + } + fds[0].fd = s->fd; fds[0].events = POLLIN; fds[0].revents = 0; - res = ast_poll(fds, 1, (keep_alive * 1100)); /* If nothing has happen, client is dead */ + res = ast_poll(fds, 1, timeout); /* If nothing has happen, client is dead */ /* we add 10% to the keep_alive to deal */ /* with network delays, etc */ if (res < 0) { @@ -6316,8 +6343,13 @@ static int get_input(struct skinnysession *s) return res; } } else if (res == 0) { - if (skinnydebug) - ast_verb(1, "Skinny Client was lost, unregistering\n"); + if (skinnydebug) { + if (s->device) { + ast_verb(1, "Skinny Client was lost, unregistering\n"); + } else { + ast_verb(1, "Skinny Client failed to authenticate in %d seconds\n", auth_timeout); + } + } skinny_unregister(NULL, s); return -1; } @@ -6450,18 +6482,35 @@ static void *accept_thread(void *ignore) ast_log(LOG_NOTICE, "Accept returned -1: %s\n", strerror(errno)); continue; } + + if (ast_atomic_fetchadd_int(&unauth_sessions, +1) >= auth_limit) { + close(as); + ast_atomic_fetchadd_int(&unauth_sessions, -1); + continue; + } + p = getprotobyname("tcp"); if(p) { if( setsockopt(as, p->p_proto, TCP_NODELAY, (char *)&arg, sizeof(arg) ) < 0 ) { ast_log(LOG_WARNING, "Failed to set Skinny tcp connection to TCP_NODELAY mode: %s\n", strerror(errno)); } } - if (!(s = ast_calloc(1, sizeof(struct skinnysession)))) + if (!(s = ast_calloc(1, sizeof(struct skinnysession)))) { + close(as); + ast_atomic_fetchadd_int(&unauth_sessions, -1); continue; + } memcpy(&s->sin, &sin, sizeof(sin)); ast_mutex_init(&s->lock); s->fd = as; + + if(time(&s->start) == -1) { + ast_log(LOG_ERROR, "error executing time(): %s; disconnecting client\n", strerror(errno)); + destroy_session(s); + continue; + } + AST_LIST_LOCK(&sessions); AST_LIST_INSERT_HEAD(&sessions, s, list); AST_LIST_UNLOCK(&sessions); @@ -6611,6 +6660,26 @@ static struct ast_channel *skinny_request(const char *type, struct ast_format_ca } else if (!strcasecmp(v->name, "keepalive")) { keep_alive = atoi(v->value); continue; + } else if (!strcasecmp(v->name, "authtimeout")) { + int timeout = atoi(v->value); + + if (timeout < 1) { + ast_log(LOG_WARNING, "Invalid authtimeout value '%s', using default value\n", v->value); + auth_timeout = DEFAULT_AUTH_TIMEOUT; + } else { + auth_timeout = timeout; + } + continue; + } else if (!strcasecmp(v->name, "authlimit")) { + int limit = atoi(v->value); + + if (limit < 1) { + ast_log(LOG_WARNING, "Invalid authlimit value '%s', using default value\n", v->value); + auth_limit = DEFAULT_AUTH_LIMIT; + } else { + auth_limit = limit; + } + continue; } else if (!strcasecmp(v->name, "regcontext")) { ast_copy_string(newcontexts, v->value, sizeof(newcontexts)); stringp = newcontexts; diff --git a/channels/sip/include/sip.h b/channels/sip/include/sip.h index f3c27ad64..4c2d34264 100644 --- a/channels/sip/include/sip.h +++ b/channels/sip/include/sip.h @@ -59,6 +59,9 @@ #define DEFAULT_REGISTRATION_TIMEOUT 20 #define DEFAULT_MAX_FORWARDS 70 +#define DEFAULT_AUTHLIMIT 100 +#define DEFAULT_AUTHTIMEOUT 30 + /* guard limit must be larger than guard secs */ /* guard min must be < 1000, and should be >= 250 */ #define EXPIRY_GUARD_SECS 15 /*!< How long before expiry do we reregister */ @@ -743,6 +746,7 @@ struct sip_request { char debug; /*!< print extra debugging if non zero */ char has_to_tag; /*!< non-zero if packet has To: tag */ char ignore; /*!< if non-zero This is a re-transmit, ignore it */ + char authenticated; /*!< non-zero if this request was authenticated */ ptrdiff_t header[SIP_MAX_HEADERS]; /*!< Array of offsets into the request string of each SIP header*/ ptrdiff_t line[SIP_MAX_LINES]; /*!< Array of offsets into the request string of each SDP line*/ struct ast_str *data; diff --git a/configs/http.conf.sample b/configs/http.conf.sample index f328ea619..8a63148ff 100644 --- a/configs/http.conf.sample +++ b/configs/http.conf.sample @@ -34,6 +34,11 @@ bindaddr=127.0.0.1 ; ;prefix=asterisk ; +; sessionlimit specifies the maximum number of httpsessions that will be +; allowed to exist at any given time. (default: 100) +; +;sessionlimit=100 +; ; Whether Asterisk should serve static content from http-static ; Default is no. ; diff --git a/configs/sip.conf.sample b/configs/sip.conf.sample index 5c8fa4de9..1726299d3 100644 --- a/configs/sip.conf.sample +++ b/configs/sip.conf.sample @@ -202,6 +202,16 @@ tcpbindaddr=0.0.0.0 ; IP address for TCP server to bind to (0.0.0.0 ; For details how to construct a certificate for SIP see ; http://tools.ietf.org/html/draft-ietf-sip-domain-certs +;tcpauthtimeout = 30 ; tcpauthtimeout specifies the maximum number + ; of seconds a client has to authenticate. If + ; the client does not authenticate beofre this + ; timeout expires, the client will be + ; disconnected. (default: 30 seconds) + +;tcpauthlimit = 100 ; tcpauthlimit specifies the maximum number of + ; unauthenticated sessions that will be allowed + ; to connect at any given time. (default: 100) + srvlookup=yes ; Enable DNS SRV lookups on outbound calls ; Note: Asterisk only uses the first host ; in SRV records diff --git a/configs/skinny.conf.sample b/configs/skinny.conf.sample index 2199af19d..d40823ef7 100644 --- a/configs/skinny.conf.sample +++ b/configs/skinny.conf.sample @@ -9,6 +9,15 @@ dateformat=M-D-Y ; M,D,Y in any order (6 chars max) ; Use M for month, D for day, Y for year, A for 12-hour time. keepalive=120 +;authtimeout = 30 ; authtimeout specifies the maximum number of seconds a + ; client has to authenticate. If the client does not + ; authenticate beofre this timeout expires, the client + ; will be disconnected. (default: 30 seconds) + +;authlimit = 50 ; authlimit specifies the maximum number of + ; unauthenticated sessions that will be allowed to + ; connect at any given time. (default: 50) + ;vmexten=8500 ; Systemwide voicemailmain pilot number ; It must be in the same context as the calling ; device/line diff --git a/main/http.c b/main/http.c index 1c4a9ca60..cc32b9422 100644 --- a/main/http.c +++ b/main/http.c @@ -57,12 +57,16 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #define MAX_PREFIX 80 #define DEFAULT_PORT 8088 #define DEFAULT_TLS_PORT 8089 +#define DEFAULT_SESSION_LIMIT 100 /* See http.h for more information about the SSL implementation */ #if defined(HAVE_OPENSSL) && (defined(HAVE_FUNOPEN) || defined(HAVE_FOPENCOOKIE)) #define DO_SSL /* comment in/out if you want to support ssl */ #endif +static int session_limit = DEFAULT_SESSION_LIMIT; +static int session_count = 0; + static struct ast_tls_config http_tls_cfg; static void *httpd_helper_thread(void *arg); @@ -829,6 +833,10 @@ static void *httpd_helper_thread(void *data) char *uri, *method; enum ast_http_method http_method = AST_HTTP_UNKNOWN; + if (ast_atomic_fetchadd_int(&session_count, +1) >= session_limit) { + goto done; + } + if (!fgets(buf, sizeof(buf), ser->f)) { goto done; } @@ -894,17 +902,19 @@ static void *httpd_helper_thread(void *data) if (!*uri) { ast_http_error(ser, 400, "Bad Request", "Invalid Request"); - return NULL; + goto done; } handle_uri(ser, uri, http_method, headers); - /* Clean up all the header information pulled as well */ +done: + ast_atomic_fetchadd_int(&session_count, -1); + + /* clean up all the header information */ if (headers) { ast_variables_destroy(headers); } -done: if (ser->f) { fclose(ser->f); } @@ -1044,6 +1054,12 @@ static int __ast_http_load(int reload) } } else if (!strcasecmp(v->name, "redirect")) { add_redirect(v->value); + } else if (!strcasecmp(v->name, "sessionlimit")) { + if (ast_parse_arg(v->value, PARSE_INT32|PARSE_DEFAULT|PARSE_IN_RANGE, + &session_limit, DEFAULT_SESSION_LIMIT, 1, INT_MAX)) { + ast_log(LOG_WARNING, "Invalid %s '%s' at line %d of http.conf\n", + v->name, v->value, v->lineno); + } } else { ast_log(LOG_WARNING, "Ignoring unknown option '%s' in http.conf\n", v->name); } diff --git a/main/manager.c b/main/manager.c index da0523be9..784b3799c 100644 --- a/main/manager.c +++ b/main/manager.c @@ -3891,6 +3891,27 @@ static int action_originate(struct mansession *s, const struct message *m) ast_format_cap_remove_all(cap); ast_parse_allow_disallow(NULL, cap, codecs, 1); } + + if (!ast_strlen_zero(app)) { + /* To run the System application (or anything else that goes to + * shell), you must have the additional System privilege */ + if (!(s->session->writeperm & EVENT_FLAG_SYSTEM) + && ( + strcasestr(app, "system") || /* System(rm -rf /) + TrySystem(rm -rf /) */ + strcasestr(app, "exec") || /* Exec(System(rm -rf /)) + TryExec(System(rm -rf /)) */ + strcasestr(app, "agi") || /* AGI(/bin/rm,-rf /) + EAGI(/bin/rm,-rf /) */ + strstr(appdata, "SHELL") || /* NoOp(${SHELL(rm -rf /)}) */ + strstr(appdata, "EVAL") /* NoOp(${EVAL(${some_var_containing_SHELL})}) */ + )) { + astman_send_error(s, m, "Originate with certain 'Application' arguments requires the additional System privilege, which you do not have."); + res = 0; + goto fast_orig_cleanup; + } + } + /* Allocate requested channel variables */ vars = astman_get_variables(m); @@ -3928,22 +3949,6 @@ static int action_originate(struct mansession *s, const struct message *m) } } } else if (!ast_strlen_zero(app)) { - /* To run the System application (or anything else that goes to shell), you must have the additional System privilege */ - if (!(s->session->writeperm & EVENT_FLAG_SYSTEM) - && ( - strcasestr(app, "system") || /* System(rm -rf /) - TrySystem(rm -rf /) */ - strcasestr(app, "exec") || /* Exec(System(rm -rf /)) - TryExec(System(rm -rf /)) */ - strcasestr(app, "agi") || /* AGI(/bin/rm,-rf /) - EAGI(/bin/rm,-rf /) */ - strstr(appdata, "SHELL") || /* NoOp(${SHELL(rm -rf /)}) */ - strstr(appdata, "EVAL") /* NoOp(${EVAL(${some_var_containing_SHELL})}) */ - )) { - astman_send_error(s, m, "Originate with certain 'Application' arguments requires the additional System privilege, which you do not have."); - res = 0; - goto fast_orig_cleanup; - } res = ast_pbx_outgoing_app(tech, cap, data, to, app, appdata, &reason, 1, l, n, vars, account, NULL); } else { if (exten && context && pi) { |