Index: asterisk/channels/chan_sip.c =================================================================== RCS file: /usr/cvsroot/asterisk/channels/chan_sip.c,v retrieving revision 1.672 diff -u -r1.672 chan_sip.c --- asterisk/channels/chan_sip.c 9 Mar 2005 04:56:51 -0000 1.672 +++ asterisk/channels/chan_sip.c 11 Mar 2005 22:25:50 -0000 @@ -436,6 +436,7 @@ ASTOBJ_COMPONENTS(struct sip_user); char secret[80]; /* Password */ char md5secret[80]; /* Password in md5 */ + regex_t alloweduseragent; /* Just authenicate from a specific User agent */ char context[80]; /* Default context for incoming calls */ char cid_num[80]; /* Caller ID num */ char cid_name[80]; /* Caller ID name */ @@ -464,6 +465,7 @@ /* peer->name is the unique name of this object */ char secret[80]; /* Password */ char md5secret[80]; /* Password in MD5 */ + regex_t alloweduseragent; /* Just authenicate from a specific User agent */ char context[80]; /* Default context for incoming calls */ char username[80]; /* Temporary username until registration */ char accountcode[20]; /* Account code */ @@ -1168,6 +1170,8 @@ rpeerobjs--; else speerobjs--; + if (peer->alloweduseragent.used) + regfree(&peer->alloweduseragent); free(peer); } @@ -1270,6 +1274,8 @@ ruserobjs--; else suserobjs--; + if (user->alloweduseragent.used) + regfree(&user->alloweduseragent); free(user); } @@ -5002,7 +5008,7 @@ /*--- check_auth: Check user authorization from peer definition ---*/ /* Some actions, like REGISTER and INVITEs from peers require authentication (if peer have secret set) */ -static int check_auth(struct sip_pvt *p, struct sip_request *req, char *randdata, int randlen, char *username, char *secret, char *md5secret, char *method, char *uri, int reliable, int ignore) +static int check_auth(struct sip_pvt *p, struct sip_request *req, char *randdata, int randlen, char *username, char *secret, char *md5secret, regex_t alloweduseragent, char *method, char *uri, int reliable, int ignore) { int res = -1; char *response = "407 Proxy Authentication Required"; @@ -5020,8 +5026,10 @@ && ast_test_flag(p, SIP_OSPAUTH) && global_allowguest != 2 #endif - ) - return 0; + ) { + res=0; + goto checkuseragent; + } if (!strcasecmp(method, "REGISTER")) { /* On a REGISTER, we have to use 401 and its family of headers instead of 407 and its family of headers -- GO SIP! Whoo hoo! Two things that do the same thing but are used in @@ -5047,8 +5055,10 @@ /* If ospauth is 'exclusive' don't require further authentication */ if ((ast_test_flag(p, SIP_OSPAUTH) == SIP_OSPAUTH_EXCLUSIVE) || - (ast_strlen_zero(secret) && ast_strlen_zero(md5secret))) - return 0; + (ast_strlen_zero(secret) && ast_strlen_zero(md5secret))) { + res=0; + goto checkuseragent; + } } #endif authtoken = get_header(req, reqheader); @@ -5145,6 +5155,13 @@ } /* Assume success ;-) */ } +checkuseragent: + if (!res && alloweduseragent.used) { + if (regexec(&alloweduseragent, p->useragent, (size_t) 0, NULL, 0)) { + ast_verbose(VERBOSE_PREFIX_3 "Invalid User-agent '%s' from '%s'.\n", p->useragent,username); + res = 1; + } + } return res; } @@ -5209,7 +5226,7 @@ } else { ast_copy_flags(p, peer, SIP_NAT); transmit_response(p, "100 Trying", req); - if (!(res = check_auth(p, req, p->randdata, sizeof(p->randdata), peer->name, peer->secret, peer->md5secret, "REGISTER", uri, 0, ignore))) { + if (!(res = check_auth(p, req, p->randdata, sizeof(p->randdata), peer->name, peer->secret, peer->md5secret, peer->alloweduseragent, "REGISTER", uri, 0, ignore))) { sip_cancel_destroy(p); if (parse_contact(p, peer, req)) { ast_log(LOG_WARNING, "Failed to parse contact info\n"); @@ -5747,7 +5764,7 @@ ast_log(LOG_DEBUG, "Setting NAT on VRTP to %d\n", (ast_test_flag(p, SIP_NAT) & SIP_NAT_ROUTE)); ast_rtp_setnat(p->vrtp, (ast_test_flag(p, SIP_NAT) & SIP_NAT_ROUTE)); } - if (!(res = check_auth(p, req, p->randdata, sizeof(p->randdata), user->name, user->secret, user->md5secret, cmd, uri, reliable, ignore))) { + if (!(res = check_auth(p, req, p->randdata, sizeof(p->randdata), user->name, user->secret, user->md5secret, user->alloweduseragent, cmd, uri, reliable, ignore))) { sip_cancel_destroy(p); ast_copy_flags(p, user, SIP_PROMISCREDIR | SIP_DTMF | SIP_REINVITE); /* If we have a call limit, set flag */ @@ -5828,7 +5845,7 @@ p->peersecret[0] = '\0'; p->peermd5secret[0] = '\0'; } - if (!(res = check_auth(p, req, p->randdata, sizeof(p->randdata), peer->name, p->peersecret, p->peermd5secret, cmd, uri, reliable, ignore))) { + if (!(res = check_auth(p, req, p->randdata, sizeof(p->randdata), peer->name, p->peersecret, p->peermd5secret, peer->alloweduseragent, cmd, uri, reliable, ignore))) { ast_copy_flags(p, peer, SIP_PROMISCREDIR | SIP_DTMF | SIP_REINVITE); /* If we have a call limit, set flag */ if (peer->incominglimit) @@ -5885,7 +5902,7 @@ #ifdef OSP_SUPPORT else if (global_allowguest == 2) { ast_copy_flags(p, &global_flags, SIP_OSPAUTH); - res = check_auth(p, req, p->randdata, sizeof(p->randdata), "", "", "", cmd, uri, reliable, ignore); + res = check_auth(p, req, p->randdata, sizeof(p->randdata), "", "", "", NULL, cmd, uri, reliable, ignore); } #endif } @@ -9080,6 +9097,7 @@ /* set the usage flag to a sane staring value*/ user->inUse = 0; user->outUse = 0; + user->alloweduseragent.used = 0; ast_copy_flags(user, &global_flags, SIP_PROMISCREDIR | SIP_TRUSTRPID | SIP_USECLIENTCODE | SIP_DTMF | SIP_NAT | SIP_REINVITE | SIP_INSECURE | SIP_PROG_INBAND | SIP_OSPAUTH); user->capability = global_capability; user->prefs = prefs; @@ -9113,6 +9131,9 @@ strncpy(user->secret, v->value, sizeof(user->secret)-1); } else if (!strcasecmp(v->name, "md5secret")) { strncpy(user->md5secret, v->value, sizeof(user->md5secret)-1); + } else if (!strcasecmp(v->name, "alloweduseragent")) { + if (regcomp(&user->alloweduseragent, v->value, REG_EXTENDED|REG_NOSUB)) + user->alloweduseragent.used = 0; } else if (!strcasecmp(v->name, "callerid")) { ast_callerid_split(v->value, user->cid_name, sizeof(user->cid_name), user->cid_num, sizeof(user->cid_num)); } else if (!strcasecmp(v->name, "callgroup")) { @@ -9251,6 +9272,7 @@ ast_copy_flags(peer, &global_flags, SIP_USEREQPHONE); peer->secret[0] = '\0'; peer->md5secret[0] = '\0'; + peer->alloweduseragent.used = 0; peer->cid_num[0] = '\0'; peer->cid_name[0] = '\0'; peer->fromdomain[0] = '\0'; @@ -9284,9 +9306,12 @@ strncpy(peer->name, v->value, sizeof(peer->name)-1); else if (!strcasecmp(v->name, "secret")) strncpy(peer->secret, v->value, sizeof(peer->secret)-1); - else if (!strcasecmp(v->name, "md5secret")) - strncpy(peer->md5secret, v->value, sizeof(peer->md5secret)-1); - else if (!strcasecmp(v->name, "callerid")) { + else if (!strcasecmp(v->name, "md5secret")) + strncpy(peer->md5secret, v->value, sizeof(peer->md5secret)-1); + else if (!strcasecmp(v->name, "alloweduseragent")) { + if (regcomp(&peer->alloweduseragent, v->value, REG_EXTENDED|REG_NOSUB)) + peer->alloweduseragent.used = 0; + } else if (!strcasecmp(v->name, "callerid")) { ast_callerid_split(v->value, peer->cid_name, sizeof(peer->cid_name), peer->cid_num, sizeof(peer->cid_num)); } else if (!strcasecmp(v->name, "context")) strncpy(peer->context, v->value, sizeof(peer->context)-1); Index: asterisk/configs/sip.conf.sample =================================================================== RCS file: /usr/cvsroot/asterisk/configs/sip.conf.sample,v retrieving revision 1.59 diff -u -r1.59 sip.conf.sample --- asterisk/configs/sip.conf.sample 13 Feb 2005 16:40:56 -0000 1.59 +++ asterisk/configs/sip.conf.sample 11 Mar 2005 22:25:50 -0000 @@ -180,6 +180,7 @@ ; deny deny ; secret secret ; md5secret md5secret +; alloweduseragent alloweduseragent ; dtmfmode dtmfmode ; canreinvite canreinvite ; nat nat @@ -283,6 +284,8 @@ ;type=friend ; Friends place calls and receive calls ;context=from-sip ; Context for incoming calls from this user ;secret=blah +;alloweduseragent=snom190|snom360 ; allow to register from Snom 190 or Snom 360 +;alloweduseragent=snom190-3.56u ; just allow to register from Snom 190 firmware 3.56u ;language=de ; Use German prompts for this user ;host=dynamic ; This peer register with us ;dtmfmode=inband ; Choices are inband, rfc2833, or info