]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Added limits to the number of unauthenticated sessions TCP based protocols are allowe...
authorMatthew Nicholson <mnicholson@digium.com>
Thu, 21 Apr 2011 18:49:54 +0000 (18:49 +0000)
committerMatthew Nicholson <mnicholson@digium.com>
Thu, 21 Apr 2011 18:49:54 +0000 (18:49 +0000)
Unrelated, the manager interface now properly checks if the user has the "system" privilege before executing shell commands via the Originate action.

AST-2011-005
AST-2011-006

(closes issue #18787)
Reported by: kobaz

(related to issue #18996)
Reported by: tzafrir

git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.1@314685 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channels/chan_sip.c
channels/chan_skinny.c
configs/http.conf.sample
configs/sip.conf.sample
configs/skinny.conf.sample
main/manager.c

index 3a10a6d18a0ce4c91cd9f4e6445d00ebb6560d63..133288146a5ec92cf4d21ce58071c708c8d2700f 100644 (file)
@@ -225,6 +225,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #define DEFAULT_MAX_EXPIRY      3600
 #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 */
@@ -272,6 +275,10 @@ static int default_expiry = DEFAULT_DEFAULT_EXPIRY;
 
 #define SDP_MAX_RTPMAP_CODECS        32               /*!< Maximum number of codecs allowed in received SDP */
 
+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 =
 {
@@ -903,6 +910,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 */
        /* Array of offsets into the request string of each SIP header*/
        ptrdiff_t header[SIP_MAX_HEADERS];
        /* Array of offsets into the request string of each SDP line*/
@@ -2540,19 +2548,46 @@ 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 */
 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.
@@ -2561,6 +2596,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;
                }
@@ -2590,13 +2641,41 @@ static void *_sip_tcp_helper_thread(struct sip_pvt *pvt, struct ast_tcptls_sessi
        if (!(reqcpy.data = ast_str_create(SIP_MIN_PACKET)))
                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,
@@ -2629,6 +2708,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);
@@ -2646,6 +2748,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);
@@ -2702,6 +2827,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");
@@ -19111,6 +19240,8 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
                        set_t38_capabilities(p);
                }
 
+               req->authenticated = 1;
+
                /* We have a succesful authentication, process the SDP portion if there is one */
                if (find_sdp(req)) {
                        if (process_sdp(p, req, SDP_T38_INITIATE)) {
@@ -20633,8 +20764,10 @@ static int handle_request_register(struct sip_pvt *p, struct sip_request *req, s
                        get_header(req, "To"), ast_inet_ntoa(sin->sin_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
@@ -21065,6 +21198,11 @@ static int handle_request_do(struct sip_request *req, struct sockaddr_in *sin)
        }
        p->recv = *sin;
 
+       /* 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));
 
@@ -23514,6 +23652,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;
 
        global_matchexterniplocally = FALSE;
 
@@ -23731,6 +23871,18 @@ static int reload_config(enum channelreloadreason reason)
                        default_expiry = atoi(v->value);
                        if (default_expiry < 1)
                                default_expiry = DEFAULT_DEFAULT_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;
index 9bffdb7fc7a3b6dcdfe7f68b876bc08c74a624f1..243dfb65ecd3ae48885754767c0ea0e0ff184b4f 100644 (file)
@@ -92,6 +92,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;
@@ -103,6 +105,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 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 */
@@ -1256,6 +1261,7 @@ static AST_LIST_HEAD_STATIC(devices, skinny_device);
 struct skinnysession {
        pthread_t t;
        ast_mutex_t lock;
+       time_t start;
        struct sockaddr_in sin;
        int fd;
        char inbuf[SKINNY_MAX_PACKET];
@@ -4215,6 +4221,8 @@ static int handle_register_message(struct skinny_req *req, struct skinnysession
 
                return 0;
        }
+       ast_atomic_fetchadd_int(&unauth_sessions, -1);
+
        ast_verb(3, "Device '%s' successfully registered\n", name);
 
        d = s->device;
@@ -5879,6 +5887,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);
@@ -5894,13 +5905,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) {
@@ -5909,8 +5937,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;
        }
@@ -6044,18 +6077,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);
@@ -6221,6 +6271,24 @@ static int reload_config(void)
                        }
                } else if (!strcasecmp(v->name, "keepalive")) {
                        keep_alive = atoi(v->value);
+               } 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;
+                       }
+               } 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;
+                       }
                } else if (!strcasecmp(v->name, "vmexten")) {
                        ast_copy_string(vmexten, v->value, sizeof(vmexten));
                } else if (!strcasecmp(v->name, "regcontext")) {
index f15c9cf727dd5b11755679efdcbfc104e3f8b4fb..6da4ca67b30b48f6e153eb821adef0c99256fe3c 100644 (file)
@@ -32,6 +32,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.
 ;
index 77d464aed3933673bceab6af2e67d79ef334e390..0eadae35d12007dd035b59cbbac2fad912761544 100644 (file)
@@ -122,6 +122,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)
+
 ;tlscertfile=asterisk.pem       ; Certificate file (*.pem only) to use for TLS connections 
                                 ; default is to look for "asterisk.pem" in current directory
 
index 389e986fd4ae881310227d9aafaacf07fd20f89f..525966f718830457410eec6041b9fb932a5da7e5 100644 (file)
@@ -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
index f774c7e8daf348fea2d1b15c5c192cce65cde2ec..5b9a1e82cb8543d16ebe2b0528b76b68d2e094f2 100644 (file)
@@ -2472,6 +2472,24 @@ static int action_originate(struct mansession *s, const struct message *m)
                format = 0;
                ast_parse_allow_disallow(NULL, &format, 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") == 0 || /* 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.");
+                       return 0;
+               }
+       }
        if (ast_true(async)) {
                struct fast_originate_helper *fast = ast_calloc(1, sizeof(*fast));
                if (!fast) {
@@ -2502,21 +2520,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") == 0 || /* 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.");
-                       return 0;
-               }
                res = ast_pbx_outgoing_app(tech, format, data, to, app, appdata, &reason, 1, l, n, vars, account, NULL);
        } else {
                if (exten && context && pi)