And now the trunk version! Add an option for IAX2 users that allows you to set how...
authorJoshua Colp <jcolp@digium.com>
Tue, 11 Jul 2006 19:03:56 +0000 (19:03 +0000)
committerJoshua Colp <jcolp@digium.com>
Tue, 11 Jul 2006 19:03:56 +0000 (19:03 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@37380 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channels/chan_iax2.c
configs/iax.conf.sample

index 97f87d5..7dfbd44 100644 (file)
@@ -248,7 +248,7 @@ enum {
        IAX_USEJITTERBUF =      (1 << 5),       /*!< Use jitter buffer */
        IAX_DYNAMIC =           (1 << 6),       /*!< dynamic peer */
        IAX_SENDANI =           (1 << 7),       /*!< Send ANI along with CallerID */
-       /* (1 << 8) is currently unused due to the deprecation of an old option. Go ahead, take it! */  
+        /* (1 << 8) is currently unused due to the deprecation of an old option. Go ahead, take it! */
        IAX_ALREADYGONE =       (1 << 9),       /*!< Already disconnected */
        IAX_PROVISION =         (1 << 10),      /*!< This is a provisioning request */
        IAX_QUELCH =            (1 << 11),      /*!< Whether or not we quelch audio */
@@ -263,7 +263,8 @@ enum {
        IAX_FORCEJITTERBUF =    (1 << 20),      /*!< Force jitterbuffer, even when bridged to a channel that can take jitter */ 
        IAX_RTIGNOREREGEXPIRE = (1 << 21),      /*!< When using realtime, ignore registration expiration */
        IAX_TRUNKTIMESTAMPS =   (1 << 22),      /*!< Send trunk timestamps */
-       IAX_TRANSFERMEDIA =     (1 << 23)   /*!< When doing IAX2 transfers, transfer media only */
+       IAX_TRANSFERMEDIA =     (1 << 23),      /*!< When doing IAX2 transfers, transfer media only */
+       IAX_MAXAUTHREQ =        (1 << 24),      /*!< Maximum outstanding AUTHREQ restriction is in place */
 } iax2_flags;
 
 static int global_rtautoclear = 120;
@@ -284,6 +285,8 @@ struct iax2_user {
        int amaflags;
        unsigned int flags;
        int capability;
+       int maxauthreq; /*!< Maximum allowed outstanding AUTHREQs */
+       int curauthreq; /*!< Current number of outstanding AUTHREQs */
        char cid_num[AST_MAX_EXTENSION];
        char cid_name[AST_MAX_EXTENSION];
        struct ast_codec_pref prefs;
@@ -1616,6 +1619,20 @@ static int send_packet(struct iax_frame *f)
 
 static void iax2_destroy_helper(struct chan_iax2_pvt *pvt)
 {
+       struct iax2_user *user = NULL;
+
+       /* Decrement AUTHREQ count if needed */
+       if (ast_test_flag(pvt, IAX_MAXAUTHREQ)) {
+               AST_LIST_LOCK(&users);
+               AST_LIST_TRAVERSE(&users, user, entry) {
+                       if (!strcmp(user->name, pvt->username)) {
+                               user->curauthreq--;
+                               break;
+                       }
+               }
+               AST_LIST_UNLOCK(&users);
+               ast_clear_flag(pvt, IAX_MAXAUTHREQ);
+       }
        /* No more pings or lagrq's */
        if (pvt->pingid > -1)
                ast_sched_del(sched, pvt->pingid);
@@ -4524,7 +4541,7 @@ static int check_access(int callno, struct sockaddr_in *sin, struct iax_ies *ies
        int version = 2;
        struct iax2_user *user = NULL, *best = NULL;
        int bestscore = 0;
-       int gotcapability=0;
+       int gotcapability = 0;
        char iabuf[INET_ADDRSTRLEN];
        struct ast_variable *v = NULL, *tmpvar = NULL;
 
@@ -4643,6 +4660,9 @@ static int check_access(int callno, struct sockaddr_in *sin, struct iax_ies *ies
                                iaxs[callno]->vars = tmpvar;
                        }
                }
+               /* If a max AUTHREQ restriction is in place, activate it */
+               if (user->maxauthreq > 0)
+                       ast_set_flag(iaxs[callno], IAX_MAXAUTHREQ);
                iaxs[callno]->prefs = user->prefs;
                ast_copy_flags(iaxs[callno], user, IAX_CODEC_USER_FIRST);
                ast_copy_flags(iaxs[callno], user, IAX_CODEC_NOPREFS);
@@ -4745,9 +4765,35 @@ static void merge_encryption(struct chan_iax2_pvt *p, unsigned int enc)
 
 static int authenticate_request(struct chan_iax2_pvt *p)
 {
+       struct iax2_user *user = NULL;
        struct iax_ie_data ied;
-       int res;
+       int res = -1, authreq_restrict = 0;
+
        memset(&ied, 0, sizeof(ied));
+
+       /* If an AUTHREQ restriction is in place, make sure we can send an AUTHREQ back */
+       if (ast_test_flag(p, IAX_MAXAUTHREQ)) {
+               AST_LIST_LOCK(&users);
+               AST_LIST_TRAVERSE(&users, user, entry) {
+                       if (!strcmp(user->name, p->username)) {
+                               if (user->curauthreq == user->maxauthreq)
+                                       authreq_restrict = 1;
+                               else
+                                       user->curauthreq++;
+                               break;
+                       }
+               }
+               AST_LIST_UNLOCK(&users);
+       }
+
+       /* If the AUTHREQ limit test failed, send back an error */
+       if (authreq_restrict) {
+               iax_ie_append_str(&ied, IAX_IE_CAUSE, "Unauthenticated call limit reached");
+               iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_CALL_REJECTED);
+               send_command_final(p, AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied.buf, ied.pos, -1);
+               return 0;
+       }
+
        iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, p->authmethods);
        if (p->authmethods & (IAX_AUTH_MD5 | IAX_AUTH_RSA)) {
                snprintf(p->challenge, sizeof(p->challenge), "%d", (int)ast_random());
@@ -4755,10 +4801,14 @@ static int authenticate_request(struct chan_iax2_pvt *p)
        }
        if (p->encmethods)
                iax_ie_append_short(&ied, IAX_IE_ENCRYPTION, p->encmethods);
+
        iax_ie_append_str(&ied,IAX_IE_USERNAME, p->username);
+
        res = send_command(p, AST_FRAME_IAX, IAX_COMMAND_AUTHREQ, 0, ied.buf, ied.pos, -1);
+
        if (p->encmethods)
                ast_set_flag(p, IAX_ENCRYPTED);
+
        return res;
 }
 
@@ -4770,7 +4820,20 @@ static int authenticate_verify(struct chan_iax2_pvt *p, struct iax_ies *ies)
        char rsasecret[256] = "";
        int res = -1; 
        int x;
-       
+       struct iax2_user *user = NULL;
+
+       if (ast_test_flag(p, IAX_MAXAUTHREQ)) {
+               AST_LIST_LOCK(&users);
+               AST_LIST_TRAVERSE(&users, user, entry) {
+                       if (!strcmp(user->name, p->username)) {
+                               user->curauthreq--;
+                               break;
+                       }
+               }
+               AST_LIST_UNLOCK(&users);
+               ast_clear_flag(p, IAX_MAXAUTHREQ);
+       }
+
        if (!ast_test_flag(&p->state, IAX_STATE_AUTHENTICATED))
                return res;
        if (ies->password)
@@ -6808,8 +6871,8 @@ retryowner:
                                        merge_encryption(iaxs[fr->callno],ies.encmethods);
                                else
                                        iaxs[fr->callno]->encmethods = 0;
-                               authenticate_request(iaxs[fr->callno]);
-                               ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_AUTHENTICATED);
+                               if (!authenticate_request(iaxs[fr->callno]))
+                                       ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_AUTHENTICATED);
                                break;
                        case IAX_COMMAND_DPREQ:
                                /* Request status in the dialplan */
@@ -8320,6 +8383,7 @@ static struct iax2_user *build_user(const char *name, struct ast_variable *v, in
        struct ast_ha *oldha = NULL;
        struct iax2_context *oldcon = NULL;
        int format;
+       int oldcurauthreq = 0;
        char *varname = NULL, *varval = NULL;
        struct ast_variable *tmpvar = NULL;
        
@@ -8334,6 +8398,7 @@ static struct iax2_user *build_user(const char *name, struct ast_variable *v, in
                user = NULL;
        
        if (user) {
+               oldcurauthreq = user->curauthreq;
                oldha = user->ha;
                oldcon = user->contexts;
                user->ha = NULL;
@@ -8349,6 +8414,7 @@ static struct iax2_user *build_user(const char *name, struct ast_variable *v, in
        
        if (user) {
                memset(user, 0, sizeof(struct iax2_user));
+               user->curauthreq = oldcurauthreq;
                user->prefs = prefs;
                user->capability = iax2_capability;
                user->encmethods = iax2_encryption;
@@ -8440,6 +8506,10 @@ static struct iax2_user *build_user(const char *name, struct ast_variable *v, in
                                }
                        } else if (!strcasecmp(v->name, "inkeys")) {
                                ast_copy_string(user->inkeys, v->value, sizeof(user->inkeys));
+                       } else if (!strcasecmp(v->name, "maxauthreq")) {
+                               user->maxauthreq = atoi(v->value);
+                               if (user->maxauthreq < 0)
+                                       user->maxauthreq = 0;
                        }/* else if (strcasecmp(v->name,"type")) */
                        /*      ast_log(LOG_WARNING, "Ignoring %s\n", v->name); */
                        v = v->next;
index 0d2f270..96c604b 100644 (file)
@@ -314,6 +314,8 @@ inkeys=freeworlddialup
                        ; only media stream
 ;jitterbuffer=yes      ; Override global setting an enable jitter buffer
 ;                      ; for this user
+;maxauthreq=10          ; Set maximum number of outstanding AUTHREQs waiting for replies. Any further authentication attempts will be blocked
+;                       ; if this limit is reached until they expire or a reply is received.
 ;callerid="Mark Spencer" <(256) 428-6275>
 ;deny=0.0.0.0/0.0.0.0
 ;accountcode=markster0101